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.
- package/.brv/.obsidian/app.json +1 -0
- package/.brv/.obsidian/appearance.json +1 -0
- package/.brv/.obsidian/core-plugins.json +33 -0
- package/.brv/.obsidian/graph.json +22 -0
- package/.brv/.obsidian/workspace.json +195 -0
- package/.brv/Sin ti/314/201tulo 1.canvas" +1 -0
- package/.brv/Sin ti/314/201tulo 2.canvas" +1 -0
- package/.brv/Sin ti/314/201tulo.canvas" +1 -0
- package/.brv/_queue_status.json +1 -0
- package/.brv/config.json +5 -0
- package/.brv/context-tree/_index.md +60 -0
- package/.brv/context-tree/_manifest.json +165 -0
- package/.brv/context-tree/backend/_index.md +24 -0
- package/.brv/context-tree/backend/backend/_index.md +40 -0
- package/.brv/context-tree/backend/backend/init.abstract.md +0 -0
- package/.brv/context-tree/backend/backend/init.md +27 -0
- package/.brv/context-tree/backend/backend/init.overview.md +29 -0
- package/.brv/context-tree/backend/backend/job_tracker.abstract.md +1 -0
- package/.brv/context-tree/backend/backend/job_tracker.md +273 -0
- package/.brv/context-tree/backend/backend/job_tracker.overview.md +31 -0
- package/.brv/context-tree/backend/backend/main.abstract.md +0 -0
- package/.brv/context-tree/backend/backend/main.md +1292 -0
- package/.brv/context-tree/backend/backend/main.overview.md +30 -0
- package/.brv/context-tree/backend/backend/requirements.abstract.md +1 -0
- package/.brv/context-tree/backend/backend/requirements.md +37 -0
- package/.brv/context-tree/backend/backend/requirements.overview.md +28 -0
- package/.brv/context-tree/docs/_index.md +37 -0
- package/.brv/context-tree/docs/api/_index.md +54 -0
- package/.brv/context-tree/docs/api/context.md +11 -0
- package/.brv/context-tree/docs/api/hermes_api_openapi_specification.abstract.md +0 -0
- package/.brv/context-tree/docs/api/hermes_api_openapi_specification.md +468 -0
- package/.brv/context-tree/docs/api/hermes_api_openapi_specification.overview.md +44 -0
- package/.brv/context-tree/frontend/_index.md +48 -0
- package/.brv/context-tree/frontend/hermes_dashboard/_index.md +31 -0
- package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.abstract.md +0 -0
- package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.md +41 -0
- package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.overview.md +34 -0
- package/.brv/context-tree/frontend/src/_index.md +53 -0
- package/.brv/context-tree/frontend/src/components/_index.md +52 -0
- package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.md +161 -0
- package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.overview.md +32 -0
- package/.brv/context-tree/frontend/src/context.md +10 -0
- package/.brv/context-tree/frontend/src/functioncallingpage.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/functioncallingpage.md +34 -0
- package/.brv/context-tree/frontend/src/functioncallingpage.overview.md +26 -0
- package/.brv/context-tree/frontend/src/lib/_index.md +48 -0
- package/.brv/context-tree/frontend/src/lib/api_client_library.abstract.md +1 -0
- package/.brv/context-tree/frontend/src/lib/api_client_library.md +403 -0
- package/.brv/context-tree/frontend/src/lib/api_client_library.overview.md +69 -0
- package/.brv/context-tree/frontend/src/page.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/page.md +103 -0
- package/.brv/context-tree/frontend/src/page.overview.md +7 -0
- package/.brv/context-tree/frontend/src/settingspage.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/settingspage.md +124 -0
- package/.brv/context-tree/frontend/src/settingspage.overview.md +34 -0
- package/.brv/context-tree/frontend/src/sidebar.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/sidebar.md +170 -0
- package/.brv/context-tree/frontend/src/sidebar.overview.md +25 -0
- package/.brv/context-tree/meta/_index.md +24 -0
- package/.brv/context-tree/meta/curation_context/_index.md +24 -0
- package/.brv/context-tree/meta/curation_context/empty_context.abstract.md +4 -0
- package/.brv/context-tree/meta/curation_context/empty_context.md +35 -0
- package/.brv/context-tree/meta/curation_context/empty_context.overview.md +20 -0
- package/.brv/dream-log/drm-1777341062653.json +33 -0
- package/.brv/dream-state.json +8 -0
- package/.brv/dream.lock +0 -0
- package/.brv/review-backups/docs/api/hermes_api_openapi_specification.md +468 -0
- package/.claude/settings.local.json +7 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/app.json +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/appearance.json +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/core-plugins.json +33 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/graph.json +22 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/workspace.json +195 -0
- package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo 1.canvas" +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo 2.canvas" +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo.canvas" +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/_queue_status.json +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/config.json +5 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/_index.md +60 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/_manifest.json +165 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/_index.md +24 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/_index.md +40 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.md +27 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.overview.md +29 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.abstract.md +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.md +273 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.overview.md +31 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.md +1292 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.overview.md +30 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.abstract.md +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.md +37 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.overview.md +28 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/_index.md +37 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/_index.md +54 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/context.md +11 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.md +468 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.overview.md +44 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/_index.md +48 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/_index.md +31 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.md +41 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.overview.md +34 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/_index.md +53 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/_index.md +52 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.md +161 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.overview.md +32 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/context.md +10 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.md +34 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.overview.md +26 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/_index.md +48 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.abstract.md +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.md +403 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.overview.md +69 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.md +103 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.overview.md +7 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.md +124 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.overview.md +34 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.md +170 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.overview.md +25 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/_index.md +24 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/_index.md +24 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.abstract.md +4 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.md +35 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.overview.md +20 -0
- package/.claude/worktrees/phase-2-mcp/.brv/dream-log/drm-1777341062653.json +33 -0
- package/.claude/worktrees/phase-2-mcp/.brv/dream-state.json +8 -0
- package/.claude/worktrees/phase-2-mcp/.brv/dream.lock +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/review-backups/docs/api/hermes_api_openapi_specification.md +468 -0
- package/.claude/worktrees/phase-2-mcp/.claude/settings.local.json +13 -0
- package/.claude/worktrees/phase-2-mcp/.kilocode/package-lock.json +378 -0
- package/.claude/worktrees/phase-2-mcp/.kilocode/package.json +5 -0
- package/.claude/worktrees/phase-2-mcp/AGENTS.md +5 -0
- package/.claude/worktrees/phase-2-mcp/CLAUDE.md +29 -0
- package/.claude/worktrees/phase-2-mcp/QA_AUDIT_PLAN.md +156 -0
- package/.claude/worktrees/phase-2-mcp/README.md +316 -0
- package/.claude/worktrees/phase-2-mcp/agent-agnostic-evolution-dashboard.md +405 -0
- package/.claude/worktrees/phase-2-mcp/backend/__init__.py +0 -0
- package/.claude/worktrees/phase-2-mcp/backend/collectors/__init__.py +0 -0
- package/.claude/worktrees/phase-2-mcp/backend/collectors/claude_code_collector.py +277 -0
- package/.claude/worktrees/phase-2-mcp/backend/collectors/hermes_collector.py +68 -0
- package/.claude/worktrees/phase-2-mcp/backend/curator.py +512 -0
- package/.claude/worktrees/phase-2-mcp/backend/eval/__init__.py +19 -0
- package/.claude/worktrees/phase-2-mcp/backend/eval/engine.py +116 -0
- package/.claude/worktrees/phase-2-mcp/backend/eval/scorers.py +201 -0
- package/.claude/worktrees/phase-2-mcp/backend/generate_dataset.py +86 -0
- package/.claude/worktrees/phase-2-mcp/backend/job_tracker.py +232 -0
- package/.claude/worktrees/phase-2-mcp/backend/main.py +1746 -0
- package/.claude/worktrees/phase-2-mcp/backend/mcp_server.py +250 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/__init__.py +24 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/cycle_orchestrator.py +270 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/delta_validator.py +191 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/dspy_compiler.py +315 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/gepa_strategist.py +213 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/models.py +260 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/skill_deployer.py +195 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/trace_ingestion.py +142 -0
- package/.claude/worktrees/phase-2-mcp/backend/requirements.txt +6 -0
- package/.claude/worktrees/phase-2-mcp/backend/sdd_evolve.py +459 -0
- package/.claude/worktrees/phase-2-mcp/backend/skill_detector.py +227 -0
- package/.claude/worktrees/phase-2-mcp/backend/skill_registry.py +289 -0
- package/.claude/worktrees/phase-2-mcp/backend/storage/__init__.py +5 -0
- package/.claude/worktrees/phase-2-mcp/backend/storage/run_store.py +393 -0
- package/.claude/worktrees/phase-2-mcp/backend/storage/schema.sql +99 -0
- package/.claude/worktrees/phase-2-mcp/backend/validate_evolution.py +267 -0
- package/.claude/worktrees/phase-2-mcp/components.json +28 -0
- package/.claude/worktrees/phase-2-mcp/docs/api/hermes-api.openapi.yaml +438 -0
- package/.claude/worktrees/phase-2-mcp/docs/hero.svg +148 -0
- package/.claude/worktrees/phase-2-mcp/eslint.config.mjs +18 -0
- package/.claude/worktrees/phase-2-mcp/install.sh +245 -0
- package/.claude/worktrees/phase-2-mcp/next-env.d.ts +6 -0
- package/.claude/worktrees/phase-2-mcp/next.config.ts +32 -0
- package/.claude/worktrees/phase-2-mcp/package-lock.json +11936 -0
- package/.claude/worktrees/phase-2-mcp/package.json +41 -0
- package/.claude/worktrees/phase-2-mcp/pnpm-workspace.yaml +4 -0
- package/.claude/worktrees/phase-2-mcp/postcss.config.mjs +7 -0
- package/.claude/worktrees/phase-2-mcp/public/file.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Bold.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Heavy.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Medium.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Regular.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Semibold.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Bold.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Heavy.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Medium.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Regular.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Semibold.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/globe.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/public/next.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/public/theme-preview.html +257 -0
- package/.claude/worktrees/phase-2-mcp/public/vercel.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/public/window.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/run.sh +26 -0
- package/.claude/worktrees/phase-2-mcp/skills-lock.json +10 -0
- package/.claude/worktrees/phase-2-mcp/specs/event-schema.md +223 -0
- package/.claude/worktrees/phase-2-mcp/specs/examples/run.jsonl +3 -0
- package/.claude/worktrees/phase-2-mcp/src/app/api/[...path]/route.ts +55 -0
- package/.claude/worktrees/phase-2-mcp/src/app/api/auth/token/route.ts +22 -0
- package/.claude/worktrees/phase-2-mcp/src/app/evolution/page.tsx +589 -0
- package/.claude/worktrees/phase-2-mcp/src/app/favicon.ico +0 -0
- package/.claude/worktrees/phase-2-mcp/src/app/globals.css +321 -0
- package/.claude/worktrees/phase-2-mcp/src/app/layout.tsx +63 -0
- package/.claude/worktrees/phase-2-mcp/src/app/page.tsx +70 -0
- package/.claude/worktrees/phase-2-mcp/src/app/skills/page.tsx +369 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ApiConfigCard.tsx +199 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.css +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.d.ts +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.jsx +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/CoreLoopToggle.tsx +111 -0
- package/.claude/worktrees/phase-2-mcp/src/components/EnvironmentStatus.tsx +176 -0
- package/.claude/worktrees/phase-2-mcp/src/components/EvolutionBackground.tsx +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ReactQueryProvider.tsx +24 -0
- package/.claude/worktrees/phase-2-mcp/src/components/Sidebar.tsx +247 -0
- package/.claude/worktrees/phase-2-mcp/src/components/SkillDiffViewer.tsx +154 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ThemeAwareBackground.tsx +67 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ThemeToggle.tsx +54 -0
- package/.claude/worktrees/phase-2-mcp/src/components/WelcomeHero.tsx +77 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/ClickSpark.tsx +116 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/CountUp.tsx +98 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/DarkSelect.tsx +95 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/DecryptedText.tsx +161 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/ElectricBorder.tsx +184 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/GlitchText.tsx +34 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/ShinyText.tsx +55 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/SpotlightCard.tsx +42 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/TextType.tsx +95 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/index.ts +9 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/CuratorPage.tsx +632 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/DatasetPage.tsx +271 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/EvolutionPage.tsx +676 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/FunctionCallingPage.tsx +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/LogsPage.tsx +272 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/MetricsPage.tsx +246 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/OverviewPage.tsx +420 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/SettingsPage.tsx +88 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/SkillStudioPage.tsx +376 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/animated-theme-toggler.tsx +97 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/button.tsx +67 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/card.tsx +103 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/input.tsx +19 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/separator.tsx +28 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/sheet.tsx +147 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/sidebar.tsx +702 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/skeleton.tsx +13 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/theme-toggle.tsx +272 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/tooltip.tsx +57 -0
- package/.claude/worktrees/phase-2-mcp/src/hooks/use-mobile.ts +19 -0
- package/.claude/worktrees/phase-2-mcp/src/lib/api.ts +455 -0
- package/.claude/worktrees/phase-2-mcp/src/lib/queryClient.ts +12 -0
- package/.claude/worktrees/phase-2-mcp/src/lib/utils.ts +6 -0
- package/.claude/worktrees/phase-2-mcp/stitch/agent_dashboard/DESIGN_SPEC.md +521 -0
- package/.claude/worktrees/phase-2-mcp/stitch/agent_dashboard/prototype.html +676 -0
- package/.claude/worktrees/phase-2-mcp/stitch/curator_workspace/code.html +448 -0
- package/.claude/worktrees/phase-2-mcp/stitch/curator_workspace/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/datasets/code.html +479 -0
- package/.claude/worktrees/phase-2-mcp/stitch/datasets/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/evolution_history/code.html +461 -0
- package/.claude/worktrees/phase-2-mcp/stitch/evolution_history/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/hermes_dashboard/DESIGN.md +192 -0
- package/.claude/worktrees/phase-2-mcp/stitch/hermes_dashboard/DESIGN_SPEC.md +455 -0
- package/.claude/worktrees/phase-2-mcp/stitch/hermes_overview/code.html +399 -0
- package/.claude/worktrees/phase-2-mcp/stitch/hermes_overview/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/live_logs/code.html +324 -0
- package/.claude/worktrees/phase-2-mcp/stitch/live_logs/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/skill_hub/code.html +596 -0
- package/.claude/worktrees/phase-2-mcp/stitch/skill_hub/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/system_metrics/code.html +527 -0
- package/.claude/worktrees/phase-2-mcp/stitch/system_metrics/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/system_settings/code.html +257 -0
- package/.claude/worktrees/phase-2-mcp/stitch/system_settings/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/test_dashboard.py +201 -0
- package/.claude/worktrees/phase-2-mcp/tests/collectors/__init__.py +0 -0
- package/.claude/worktrees/phase-2-mcp/tests/collectors/fixtures/sample_session.jsonl +7 -0
- package/.claude/worktrees/phase-2-mcp/tests/collectors/test_claude_code_collector.py +171 -0
- package/.claude/worktrees/phase-2-mcp/tests/collectors/test_hermes_collector.py +167 -0
- package/.claude/worktrees/phase-2-mcp/tests/eval/test_engine.py +234 -0
- package/.claude/worktrees/phase-2-mcp/tests/eval/test_scorers.py +249 -0
- package/.claude/worktrees/phase-2-mcp/tests/storage/__init__.py +0 -0
- package/.claude/worktrees/phase-2-mcp/tests/storage/test_run_store.py +359 -0
- package/.claude/worktrees/phase-2-mcp/tests/test_curator.py +559 -0
- package/.claude/worktrees/phase-2-mcp/tests/test_mcp_server.py +114 -0
- package/.claude/worktrees/phase-2-mcp/tsconfig.json +34 -0
- package/.env.example +72 -0
- package/.kilocode/package-lock.json +378 -0
- package/.kilocode/package.json +5 -0
- package/AGENTS.md +5 -0
- package/CLAUDE.md +29 -0
- package/QA_AUDIT_PLAN.md +156 -0
- package/README.md +355 -0
- package/agent-agnostic-evolution-dashboard.md +405 -0
- package/backend/__init__.py +0 -0
- package/backend/collectors/__init__.py +0 -0
- package/backend/collectors/claude_code_collector.py +277 -0
- package/backend/collectors/hermes_collector.py +68 -0
- package/backend/curator.py +512 -0
- package/backend/eval/__init__.py +19 -0
- package/backend/eval/engine.py +116 -0
- package/backend/eval/scorers.py +201 -0
- package/backend/generate_dataset.py +86 -0
- package/backend/job_tracker.py +232 -0
- package/backend/main.py +1746 -0
- package/backend/mcp_server.py +250 -0
- package/backend/promethean/__init__.py +24 -0
- package/backend/promethean/cycle_orchestrator.py +270 -0
- package/backend/promethean/delta_validator.py +191 -0
- package/backend/promethean/dspy_compiler.py +315 -0
- package/backend/promethean/gepa_strategist.py +213 -0
- package/backend/promethean/models.py +260 -0
- package/backend/promethean/skill_deployer.py +195 -0
- package/backend/promethean/trace_ingestion.py +142 -0
- package/backend/requirements.txt +6 -0
- package/backend/sdd_evolve.py +459 -0
- package/backend/skill_detector.py +227 -0
- package/backend/skill_registry.py +289 -0
- package/backend/storage/__init__.py +5 -0
- package/backend/storage/run_store.py +393 -0
- package/backend/storage/schema.sql +99 -0
- package/backend/validate_evolution.py +267 -0
- package/bin/genoma.js +250 -0
- package/components.json +28 -0
- package/docs/api/hermes-api.openapi.yaml +438 -0
- package/docs/hero.svg +148 -0
- package/eslint.config.mjs +18 -0
- package/install.sh +245 -0
- package/next-env.d.ts +6 -0
- package/next.config.ts +32 -0
- package/package.json +46 -0
- package/pnpm-workspace.yaml +4 -0
- package/postcss.config.mjs +7 -0
- package/public/file.svg +1 -0
- package/public/fonts/SF-Pro-Display-Bold.otf +0 -0
- package/public/fonts/SF-Pro-Display-Heavy.otf +0 -0
- package/public/fonts/SF-Pro-Display-Medium.otf +0 -0
- package/public/fonts/SF-Pro-Display-Regular.otf +0 -0
- package/public/fonts/SF-Pro-Display-Semibold.otf +0 -0
- package/public/fonts/SF-Pro-Text-Bold.otf +0 -0
- package/public/fonts/SF-Pro-Text-Heavy.otf +0 -0
- package/public/fonts/SF-Pro-Text-Medium.otf +0 -0
- package/public/fonts/SF-Pro-Text-Regular.otf +0 -0
- package/public/fonts/SF-Pro-Text-Semibold.otf +0 -0
- package/public/globe.svg +1 -0
- package/public/next.svg +1 -0
- package/public/theme-preview.html +257 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/run.sh +26 -0
- package/scripts/postinstall.js +50 -0
- package/skills-lock.json +10 -0
- package/specs/event-schema.md +223 -0
- package/specs/examples/run.jsonl +3 -0
- package/src/app/api/[...path]/route.ts +55 -0
- package/src/app/api/auth/token/route.ts +22 -0
- package/src/app/evolution/page.tsx +589 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +321 -0
- package/src/app/layout.tsx +63 -0
- package/src/app/page.tsx +70 -0
- package/src/app/skills/page.tsx +369 -0
- package/src/components/ApiConfigCard.tsx +199 -0
- package/src/components/ColorBends.css +1 -0
- package/src/components/ColorBends.d.ts +1 -0
- package/src/components/ColorBends.jsx +1 -0
- package/src/components/CoreLoopToggle.tsx +111 -0
- package/src/components/EnvironmentStatus.tsx +176 -0
- package/src/components/EvolutionBackground.tsx +1 -0
- package/src/components/ReactQueryProvider.tsx +24 -0
- package/src/components/Sidebar.tsx +247 -0
- package/src/components/SkillDiffViewer.tsx +154 -0
- package/src/components/ThemeAwareBackground.tsx +67 -0
- package/src/components/ThemeToggle.tsx +54 -0
- package/src/components/WelcomeHero.tsx +77 -0
- package/src/components/bits/ClickSpark.tsx +116 -0
- package/src/components/bits/CountUp.tsx +98 -0
- package/src/components/bits/DarkSelect.tsx +95 -0
- package/src/components/bits/DecryptedText.tsx +161 -0
- package/src/components/bits/ElectricBorder.tsx +184 -0
- package/src/components/bits/GlitchText.tsx +34 -0
- package/src/components/bits/ShinyText.tsx +55 -0
- package/src/components/bits/SpotlightCard.tsx +42 -0
- package/src/components/bits/TextType.tsx +95 -0
- package/src/components/bits/index.ts +9 -0
- package/src/components/pages/CuratorPage.tsx +632 -0
- package/src/components/pages/DatasetPage.tsx +271 -0
- package/src/components/pages/EvolutionPage.tsx +676 -0
- package/src/components/pages/FunctionCallingPage.tsx +1 -0
- package/src/components/pages/LogsPage.tsx +272 -0
- package/src/components/pages/MetricsPage.tsx +246 -0
- package/src/components/pages/OverviewPage.tsx +420 -0
- package/src/components/pages/SettingsPage.tsx +88 -0
- package/src/components/pages/SkillStudioPage.tsx +376 -0
- package/src/components/ui/animated-theme-toggler.tsx +97 -0
- package/src/components/ui/button.tsx +67 -0
- package/src/components/ui/card.tsx +103 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/sheet.tsx +147 -0
- package/src/components/ui/sidebar.tsx +702 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/theme-toggle.tsx +272 -0
- package/src/components/ui/tooltip.tsx +57 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/api.ts +455 -0
- package/src/lib/queryClient.ts +12 -0
- package/src/lib/utils.ts +6 -0
- package/stitch/agent_dashboard/DESIGN_SPEC.md +521 -0
- package/stitch/agent_dashboard/prototype.html +676 -0
- package/stitch/curator_workspace/code.html +448 -0
- package/stitch/curator_workspace/screen.png +0 -0
- package/stitch/datasets/code.html +479 -0
- package/stitch/datasets/screen.png +0 -0
- package/stitch/evolution_history/code.html +461 -0
- package/stitch/evolution_history/screen.png +0 -0
- package/stitch/hermes_dashboard/DESIGN.md +192 -0
- package/stitch/hermes_dashboard/DESIGN_SPEC.md +455 -0
- package/stitch/hermes_overview/code.html +399 -0
- package/stitch/hermes_overview/screen.png +0 -0
- package/stitch/live_logs/code.html +324 -0
- package/stitch/live_logs/screen.png +0 -0
- package/stitch/skill_hub/code.html +596 -0
- package/stitch/skill_hub/screen.png +0 -0
- package/stitch/system_metrics/code.html +527 -0
- package/stitch/system_metrics/screen.png +0 -0
- package/stitch/system_settings/code.html +257 -0
- package/stitch/system_settings/screen.png +0 -0
- package/test_dashboard.py +201 -0
- package/tests/collectors/__init__.py +0 -0
- package/tests/collectors/fixtures/sample_session.jsonl +7 -0
- package/tests/collectors/test_claude_code_collector.py +171 -0
- package/tests/collectors/test_hermes_collector.py +167 -0
- package/tests/eval/test_engine.py +234 -0
- package/tests/eval/test_scorers.py +249 -0
- package/tests/storage/__init__.py +0 -0
- package/tests/storage/test_run_store.py +359 -0
- package/tests/test_curator.py +559 -0
- package/tests/test_e2e_npm.py +621 -0
- package/tests/test_mcp_server.py +114 -0
- package/tsconfig.json +34 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# Agent-Agnostic Agent Intelligence Platform Plan
|
|
2
|
+
|
|
3
|
+
> **For Hermes:** Use `subagent-driven-development` only after the spec is approved. This plan is deliberately agent-agnostic so Claude Code, OpenCode, Codex, Hermes, and future agents can all emit comparable telemetry.
|
|
4
|
+
|
|
5
|
+
**Goal:** Build a vendor-neutral platform that works with *any* agent, ingests their runs through explicit collectors, normalizes execution traces, evaluates outcomes, and surfaces measurable improvements through a dashboard.
|
|
6
|
+
|
|
7
|
+
**Architecture:** The system is split into four layers: (1) collectors / adapters that ingest each agent’s native CLI or log output into a shared event schema, (2) a normalization and storage layer, (3) an evaluation engine that runs tests/scoring/benchmarks, and (4) a dashboard/API layer that reads the stored data and visualizes runs, comparisons, regressions, and suggested improvements. The dashboard does not capture runs; it is a consumer of the platform’s data.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Shared event schema in JSONL or SQLite/Postgres, CLI collectors and adapter modules per agent, evaluation workers, web dashboard, optional MCP server for agent access, and export/import hooks for CI and PR workflows.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Problem Statement
|
|
14
|
+
|
|
15
|
+
Today, agent improvements are usually trapped inside a single ecosystem. That creates three problems:
|
|
16
|
+
|
|
17
|
+
1. The data model is proprietary to one agent.
|
|
18
|
+
2. Evaluation results are not comparable across tools.
|
|
19
|
+
3. Improvement loops cannot be reused by different agents.
|
|
20
|
+
|
|
21
|
+
The product should solve the opposite problem: *one canonical telemetry and improvement layer* that any agent can plug into.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Non-Goals
|
|
26
|
+
|
|
27
|
+
- Rebuilding Claude Code, OpenCode, Codex, or Hermes internally.
|
|
28
|
+
- Forcing all agents to use the same runtime or CLI.
|
|
29
|
+
- Optimizing for pretty charts before having trustworthy data.
|
|
30
|
+
- Automating code changes without review or rollback.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Product Shape
|
|
35
|
+
|
|
36
|
+
The system should answer these questions:
|
|
37
|
+
|
|
38
|
+
- What did the agent try to do?
|
|
39
|
+
- Which tools did it call?
|
|
40
|
+
- What files or artifacts changed?
|
|
41
|
+
- Where did it fail?
|
|
42
|
+
- Did the change improve the target metric?
|
|
43
|
+
- How does one agent compare with another on the same task?
|
|
44
|
+
|
|
45
|
+
If it cannot answer those questions, it is not yet the product.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Core Concepts
|
|
50
|
+
|
|
51
|
+
### 1) Collector / Ingestor
|
|
52
|
+
A small module or wrapper that captures a native agent run from CLI output, logs, JSON, or session files and converts it into the canonical schema.
|
|
53
|
+
|
|
54
|
+
Examples:
|
|
55
|
+
- Hermes CLI collector
|
|
56
|
+
- Claude Code collector
|
|
57
|
+
- Codex collector
|
|
58
|
+
- OpenCode collector
|
|
59
|
+
|
|
60
|
+
The collector is the only layer that knows how a specific agent speaks. Everything after this point should be agent-neutral.
|
|
61
|
+
|
|
62
|
+
### 2) Canonical Run Event Schema
|
|
63
|
+
Minimum fields:
|
|
64
|
+
|
|
65
|
+
- `run_id`
|
|
66
|
+
- `agent_name`
|
|
67
|
+
- `provider`
|
|
68
|
+
- `model`
|
|
69
|
+
- `repo`
|
|
70
|
+
- `session_id`
|
|
71
|
+
- `task_name`
|
|
72
|
+
- `started_at`
|
|
73
|
+
- `ended_at`
|
|
74
|
+
- `tool_calls[]`
|
|
75
|
+
- `files_touched[]`
|
|
76
|
+
- `artifacts[]`
|
|
77
|
+
- `errors[]`
|
|
78
|
+
- `metrics{}`
|
|
79
|
+
- `eval_scores[]`
|
|
80
|
+
- `improvement_candidates[]`
|
|
81
|
+
|
|
82
|
+
### 3) Normalization + Storage Layer
|
|
83
|
+
Takes collector output, deduplicates it, stores it, and makes it queryable.
|
|
84
|
+
|
|
85
|
+
This layer owns:
|
|
86
|
+
- schema validation
|
|
87
|
+
- event normalization
|
|
88
|
+
- persistence
|
|
89
|
+
- indexing
|
|
90
|
+
|
|
91
|
+
### 4) Evaluation Engine
|
|
92
|
+
Runs deterministic checks over a run:
|
|
93
|
+
|
|
94
|
+
- unit tests
|
|
95
|
+
- lint/type checks
|
|
96
|
+
- benchmark tasks
|
|
97
|
+
- regression detection
|
|
98
|
+
- semantic scoring
|
|
99
|
+
- cost and latency scoring
|
|
100
|
+
|
|
101
|
+
### 5) Dashboard
|
|
102
|
+
Shows:
|
|
103
|
+
|
|
104
|
+
- per-run timelines
|
|
105
|
+
- agent comparisons
|
|
106
|
+
- regressions
|
|
107
|
+
- best-performing variants
|
|
108
|
+
- suggested prompt/skill/tool-description changes
|
|
109
|
+
|
|
110
|
+
The dashboard is read-only with respect to ingestion. It visualizes the state created by collectors, storage, and evaluation.
|
|
111
|
+
|
|
112
|
+
### 6) Optional Improvement Loop
|
|
113
|
+
Generates candidate improvements for:
|
|
114
|
+
|
|
115
|
+
- prompts
|
|
116
|
+
- skills
|
|
117
|
+
- tool descriptions
|
|
118
|
+
- code paths
|
|
119
|
+
|
|
120
|
+
But those changes should be gated by tests and human review.
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Architecture Decision
|
|
126
|
+
|
|
127
|
+
### Chosen path: Event-first, UI-second
|
|
128
|
+
|
|
129
|
+
Do **not** start with the dashboard UI.
|
|
130
|
+
Start with the event contract and adapters.
|
|
131
|
+
|
|
132
|
+
Why:
|
|
133
|
+
- if the schema is wrong, the UI becomes a lie
|
|
134
|
+
- if the adapters are weak, the data is noisy
|
|
135
|
+
- if the evaluator is unclear, the charts are decorative only
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## MVP Scope
|
|
140
|
+
|
|
141
|
+
The MVP should include:
|
|
142
|
+
|
|
143
|
+
1. One shared event schema
|
|
144
|
+
2. Two collectors at minimum
|
|
145
|
+
- Hermes
|
|
146
|
+
- Claude Code or Codex
|
|
147
|
+
3. A storage backend
|
|
148
|
+
4. A basic evaluator
|
|
149
|
+
5. A dashboard with:
|
|
150
|
+
- list of runs
|
|
151
|
+
- run detail view
|
|
152
|
+
- agent comparison view
|
|
153
|
+
- score trend view
|
|
154
|
+
6. Export to JSON/CSV
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Phase 1: Define the Canonical Schema
|
|
159
|
+
|
|
160
|
+
**Objective:** Establish the minimum event format that every agent can emit.
|
|
161
|
+
|
|
162
|
+
**Files:**
|
|
163
|
+
- Create: `specs/event-schema.md`
|
|
164
|
+
- Create: `specs/examples/run.jsonl`
|
|
165
|
+
- Create: `src/schema/README.md` if code exists later
|
|
166
|
+
|
|
167
|
+
**Deliverable:**
|
|
168
|
+
A written contract for runs, tools, artifacts, errors, and evaluation metrics.
|
|
169
|
+
|
|
170
|
+
**Verification:**
|
|
171
|
+
- Schema covers Hermes, Claude Code, Codex, and OpenCode without special casing.
|
|
172
|
+
- Example payloads are valid JSON.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Phase 2: Build the Hermes Collector
|
|
177
|
+
|
|
178
|
+
**Objective:** Convert Hermes CLI output, session logs, or JSON traces into the canonical schema.
|
|
179
|
+
|
|
180
|
+
**Files:**
|
|
181
|
+
- Create: `src/collectors/hermes_collector.py`
|
|
182
|
+
- Create: `tests/collectors/test_hermes_collector.py`
|
|
183
|
+
|
|
184
|
+
**What it must extract:**
|
|
185
|
+
- session metadata
|
|
186
|
+
- tool calls
|
|
187
|
+
- final output
|
|
188
|
+
- errors
|
|
189
|
+
- touched files when available
|
|
190
|
+
|
|
191
|
+
**Verification:**
|
|
192
|
+
- A sample Hermes run converts into a valid canonical event.
|
|
193
|
+
- Missing optional fields do not break the collector.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Phase 3: Build One Non-Hermes Collector
|
|
198
|
+
|
|
199
|
+
**Objective:** Prove the system is not Hermes-specific.
|
|
200
|
+
|
|
201
|
+
**Files:**
|
|
202
|
+
- Create: `src/collectors/claude_code_collector.py` or `src/collectors/codex_collector.py`
|
|
203
|
+
- Create: `tests/collectors/test_non_hermes_collector.py`
|
|
204
|
+
|
|
205
|
+
**Verification:**
|
|
206
|
+
- The output structure matches the Hermes collector output shape.
|
|
207
|
+
- A comparison test confirms parity of required fields.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Phase 4: Add Storage and Query Layer
|
|
212
|
+
|
|
213
|
+
**Objective:** Persist runs and make them queryable.
|
|
214
|
+
|
|
215
|
+
**Files:**
|
|
216
|
+
- Create: `src/storage/*.py`
|
|
217
|
+
- Create: `tests/storage/*.py`
|
|
218
|
+
|
|
219
|
+
**Storage choice:**
|
|
220
|
+
- SQLite for MVP
|
|
221
|
+
- Postgres if multi-user and remote access are needed early
|
|
222
|
+
|
|
223
|
+
**Verification:**
|
|
224
|
+
- Insert run
|
|
225
|
+
- Query by agent
|
|
226
|
+
- Query by repo
|
|
227
|
+
- Query by date
|
|
228
|
+
- Query by score
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Phase 5: Implement the Evaluation Engine
|
|
233
|
+
|
|
234
|
+
**Objective:** Score runs consistently across agents.
|
|
235
|
+
|
|
236
|
+
**Files:**
|
|
237
|
+
- Create: `src/eval/engine.py`
|
|
238
|
+
- Create: `tests/eval/test_engine.py`
|
|
239
|
+
|
|
240
|
+
**Metrics to start with:**
|
|
241
|
+
- tests pass/fail
|
|
242
|
+
- diff size
|
|
243
|
+
- number of tool calls
|
|
244
|
+
- latency
|
|
245
|
+
- token/cost estimate
|
|
246
|
+
- task success
|
|
247
|
+
|
|
248
|
+
**Verification:**
|
|
249
|
+
- The same run always scores the same way.
|
|
250
|
+
- A failing benchmark produces an explicit regression entry.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Phase 6: Build the Dashboard API
|
|
255
|
+
|
|
256
|
+
**Objective:** Expose runs, metrics, and comparisons to the UI.
|
|
257
|
+
|
|
258
|
+
**Files:**
|
|
259
|
+
- Create: `src/api/*.py`
|
|
260
|
+
- Create: `tests/api/*.py`
|
|
261
|
+
|
|
262
|
+
**Endpoints to include:**
|
|
263
|
+
- `GET /runs`
|
|
264
|
+
- `GET /runs/:id`
|
|
265
|
+
- `GET /agents`
|
|
266
|
+
- `GET /comparisons`
|
|
267
|
+
- `GET /metrics/trends`
|
|
268
|
+
|
|
269
|
+
**Verification:**
|
|
270
|
+
- API returns canonical event data without agent-specific branching.
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Phase 7: Build the Dashboard UI
|
|
275
|
+
|
|
276
|
+
**Objective:** Make the data readable and actionable.
|
|
277
|
+
|
|
278
|
+
**Files:**
|
|
279
|
+
- Create: `web/*`
|
|
280
|
+
|
|
281
|
+
**Views:**
|
|
282
|
+
- Run list
|
|
283
|
+
- Run detail
|
|
284
|
+
- Agent comparison
|
|
285
|
+
- Regression timeline
|
|
286
|
+
- Improvement suggestions
|
|
287
|
+
|
|
288
|
+
**Verification:**
|
|
289
|
+
- A user can inspect a run in under 30 seconds.
|
|
290
|
+
- A user can compare two agents on the same task.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Phase 8: Add the Improvement Loop
|
|
295
|
+
|
|
296
|
+
**Objective:** Turn observations into candidate improvements.
|
|
297
|
+
|
|
298
|
+
**Files:**
|
|
299
|
+
- Create: `src/improve/*.py`
|
|
300
|
+
- Create: `tests/improve/*.py`
|
|
301
|
+
|
|
302
|
+
**Allowed improvements:**
|
|
303
|
+
- prompt edits
|
|
304
|
+
- skill edits
|
|
305
|
+
- tool description edits
|
|
306
|
+
- code patches behind review gates
|
|
307
|
+
|
|
308
|
+
**Guardrails:**
|
|
309
|
+
- never auto-merge to main
|
|
310
|
+
- never change semantics without a regression gate
|
|
311
|
+
- never bypass tests
|
|
312
|
+
|
|
313
|
+
**Verification:**
|
|
314
|
+
- Candidate improvements are stored as proposals, not applied directly.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Phase 9: Add Agent-Readable Access
|
|
319
|
+
|
|
320
|
+
**Objective:** Let agents query the system themselves.
|
|
321
|
+
|
|
322
|
+
**Files:**
|
|
323
|
+
- Create: `src/mcp/server.py` if using MCP
|
|
324
|
+
- Create: `tests/mcp/test_server.py`
|
|
325
|
+
|
|
326
|
+
**Useful tools for agents:**
|
|
327
|
+
- get recent runs
|
|
328
|
+
- fetch latest regression
|
|
329
|
+
- fetch best-known variant
|
|
330
|
+
- compare two runs
|
|
331
|
+
- read score trend
|
|
332
|
+
|
|
333
|
+
**Verification:**
|
|
334
|
+
- At least one agent can consume the system programmatically.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Risk Register
|
|
339
|
+
|
|
340
|
+
### Risk 1: Inconsistent source formats
|
|
341
|
+
Different agents expose wildly different logs.
|
|
342
|
+
|
|
343
|
+
**Mitigation:** adapters must normalize into the same schema and drop unsupported noise.
|
|
344
|
+
|
|
345
|
+
### Risk 2: False confidence from weak evaluation
|
|
346
|
+
Pretty UI can hide bad metrics.
|
|
347
|
+
|
|
348
|
+
**Mitigation:** tests and benchmark gates must be first-class, not optional.
|
|
349
|
+
|
|
350
|
+
### Risk 3: Overfitting to one agent
|
|
351
|
+
The system accidentally becomes “Hermes with some plugins”.
|
|
352
|
+
|
|
353
|
+
**Mitigation:** require at least one non-Hermes adapter before declaring MVP complete.
|
|
354
|
+
|
|
355
|
+
### Risk 4: Improvement automation becomes unsafe
|
|
356
|
+
Auto-generated changes can regress silently.
|
|
357
|
+
|
|
358
|
+
**Mitigation:** every proposed change requires human approval plus an eval gate.
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## MVP Success Criteria
|
|
363
|
+
|
|
364
|
+
The MVP is good enough if it can:
|
|
365
|
+
|
|
366
|
+
- ingest at least two agent types
|
|
367
|
+
- normalize them into one schema
|
|
368
|
+
- score runs consistently
|
|
369
|
+
- compare runs side by side
|
|
370
|
+
- surface regressions clearly
|
|
371
|
+
- export data for downstream analysis
|
|
372
|
+
|
|
373
|
+
If it cannot do that, it is still a demo.
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Recommended Build Order
|
|
378
|
+
|
|
379
|
+
1. Canonical schema
|
|
380
|
+
2. Hermes adapter
|
|
381
|
+
3. One other agent adapter
|
|
382
|
+
4. Storage layer
|
|
383
|
+
5. Evaluation engine
|
|
384
|
+
6. Dashboard API
|
|
385
|
+
7. UI
|
|
386
|
+
8. Improvement loop
|
|
387
|
+
9. MCP access
|
|
388
|
+
|
|
389
|
+
This order is intentional. Skip it and you get a prettier version of the same ambiguity.
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Open Questions
|
|
394
|
+
|
|
395
|
+
- Should storage be SQLite first or Postgres from day one?
|
|
396
|
+
- Should the adapters read raw CLI output, session files, or both?
|
|
397
|
+
- Should the dashboard be local-first or multi-user from the start?
|
|
398
|
+
- Which metric matters most for the first release: correctness, speed, or cost?
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Final Note
|
|
403
|
+
|
|
404
|
+
This should be treated as infrastructure, not as a single-agent feature.
|
|
405
|
+
If Hermes is the only system that fits, the design is wrong.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"""Claude Code collector — converts session JSONL to CanonicalRun schema."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from backend.promethean.models import CanonicalRun, ToolCallRecord, FileTouchRecord, RunMetrics
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
CLAUDE_SESSIONS_DIR = Path.home() / ".claude" / "projects"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ClaudeCodeCollector:
|
|
13
|
+
"""Collects and normalizes Claude Code session logs into CanonicalRun events."""
|
|
14
|
+
|
|
15
|
+
VERSION = "0.1.0"
|
|
16
|
+
AGENT_NAME = "claude-code"
|
|
17
|
+
|
|
18
|
+
def collect_session(self, session_file: Path) -> Optional[CanonicalRun]:
|
|
19
|
+
"""Parse a single session JSONL file into a CanonicalRun."""
|
|
20
|
+
events = self._load_events(session_file)
|
|
21
|
+
if not events:
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
run_id = self._extract_session_id(events)
|
|
25
|
+
task_name = self._extract_task(events)
|
|
26
|
+
started_at, ended_at = self._extract_timestamps(events)
|
|
27
|
+
model = self._extract_model(events)
|
|
28
|
+
repo = self._extract_repo(events)
|
|
29
|
+
tool_calls = self._extract_tool_calls(events)
|
|
30
|
+
files_touched = self._extract_files_touched(events)
|
|
31
|
+
metrics = self._extract_metrics(events)
|
|
32
|
+
errors = self._extract_errors(events)
|
|
33
|
+
outcome = self._infer_outcome(events, errors)
|
|
34
|
+
|
|
35
|
+
return CanonicalRun(
|
|
36
|
+
run_id=run_id,
|
|
37
|
+
agent_name=self.AGENT_NAME,
|
|
38
|
+
collector="claude-code-session-collector",
|
|
39
|
+
collector_version=self.VERSION,
|
|
40
|
+
started_at=started_at,
|
|
41
|
+
ended_at=ended_at,
|
|
42
|
+
task_name=task_name,
|
|
43
|
+
outcome=outcome,
|
|
44
|
+
model=model,
|
|
45
|
+
provider="anthropic",
|
|
46
|
+
repo=repo,
|
|
47
|
+
session_id=run_id,
|
|
48
|
+
tool_calls=tool_calls,
|
|
49
|
+
files_touched=files_touched,
|
|
50
|
+
metrics=metrics,
|
|
51
|
+
errors=errors,
|
|
52
|
+
context={"cwd": self._extract_cwd(events)},
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def collect_all(self, project_path: Optional[str] = None, limit: int = 50) -> list[CanonicalRun]:
|
|
56
|
+
"""Collect runs from all sessions under a project path or all projects."""
|
|
57
|
+
runs = []
|
|
58
|
+
|
|
59
|
+
if project_path:
|
|
60
|
+
# Single project: search under that path
|
|
61
|
+
search_dir = Path(project_path)
|
|
62
|
+
else:
|
|
63
|
+
# All projects
|
|
64
|
+
search_dir = CLAUDE_SESSIONS_DIR
|
|
65
|
+
|
|
66
|
+
if not search_dir.exists():
|
|
67
|
+
return runs
|
|
68
|
+
|
|
69
|
+
count = 0
|
|
70
|
+
for session_file in sorted(search_dir.rglob("*.jsonl"), reverse=True):
|
|
71
|
+
if count >= limit:
|
|
72
|
+
break
|
|
73
|
+
try:
|
|
74
|
+
run = self.collect_session(session_file)
|
|
75
|
+
if run:
|
|
76
|
+
runs.append(run)
|
|
77
|
+
count += 1
|
|
78
|
+
except Exception:
|
|
79
|
+
continue
|
|
80
|
+
|
|
81
|
+
return runs
|
|
82
|
+
|
|
83
|
+
# ── Internal extraction methods ──────────────────────────────────
|
|
84
|
+
|
|
85
|
+
def _load_events(self, path: Path) -> list[dict]:
|
|
86
|
+
"""Load JSONL events from file. Returns empty list on error."""
|
|
87
|
+
lines = []
|
|
88
|
+
try:
|
|
89
|
+
for line in path.read_text().splitlines():
|
|
90
|
+
if not line.strip():
|
|
91
|
+
continue
|
|
92
|
+
try:
|
|
93
|
+
lines.append(json.loads(line))
|
|
94
|
+
except json.JSONDecodeError:
|
|
95
|
+
continue
|
|
96
|
+
except Exception:
|
|
97
|
+
pass
|
|
98
|
+
return lines
|
|
99
|
+
|
|
100
|
+
def _extract_session_id(self, events: list[dict]) -> str:
|
|
101
|
+
"""Extract or generate session ID from events."""
|
|
102
|
+
for event in events:
|
|
103
|
+
if isinstance(event, dict):
|
|
104
|
+
# Try attachment event first (has sessionId)
|
|
105
|
+
if event.get("type") == "attachment":
|
|
106
|
+
session_id = event.get("sessionId")
|
|
107
|
+
if session_id:
|
|
108
|
+
return session_id
|
|
109
|
+
# Try message with sessionId
|
|
110
|
+
msg = event.get("message", {})
|
|
111
|
+
if isinstance(msg, dict):
|
|
112
|
+
session_id = msg.get("sessionId")
|
|
113
|
+
if session_id:
|
|
114
|
+
return session_id
|
|
115
|
+
# Fallback: generate from first timestamp
|
|
116
|
+
import uuid
|
|
117
|
+
return str(uuid.uuid4())[:8]
|
|
118
|
+
|
|
119
|
+
def _extract_task(self, events: list[dict]) -> str:
|
|
120
|
+
"""Extract task name from first user text content."""
|
|
121
|
+
for event in events:
|
|
122
|
+
if not isinstance(event, dict):
|
|
123
|
+
continue
|
|
124
|
+
if event.get("type") == "user":
|
|
125
|
+
msg = event.get("message", {})
|
|
126
|
+
if isinstance(msg, dict):
|
|
127
|
+
content = msg.get("content", "")
|
|
128
|
+
if isinstance(content, str) and content.strip():
|
|
129
|
+
# Clean up command wrappers
|
|
130
|
+
text = content.strip()
|
|
131
|
+
if text.startswith("<command-message>"):
|
|
132
|
+
continue
|
|
133
|
+
return text[:500]
|
|
134
|
+
if isinstance(content, list):
|
|
135
|
+
for item in content:
|
|
136
|
+
if isinstance(item, dict) and item.get("type") == "text":
|
|
137
|
+
text = item.get("text", "").strip()
|
|
138
|
+
if text and not text.startswith("<command-message>"):
|
|
139
|
+
return text[:500]
|
|
140
|
+
return "unknown"
|
|
141
|
+
|
|
142
|
+
def _extract_timestamps(self, events: list[dict]) -> tuple[str, str]:
|
|
143
|
+
"""Extract start and end timestamps from events."""
|
|
144
|
+
timestamps = []
|
|
145
|
+
for event in events:
|
|
146
|
+
if isinstance(event, dict) and "timestamp" in event:
|
|
147
|
+
try:
|
|
148
|
+
timestamps.append(event["timestamp"])
|
|
149
|
+
except Exception:
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
if not timestamps:
|
|
153
|
+
from datetime import datetime, timezone
|
|
154
|
+
now = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
|
|
155
|
+
return now, now
|
|
156
|
+
|
|
157
|
+
return timestamps[0], timestamps[-1]
|
|
158
|
+
|
|
159
|
+
def _extract_model(self, events: list[dict]) -> Optional[str]:
|
|
160
|
+
"""Extract model name from assistant messages."""
|
|
161
|
+
for event in events:
|
|
162
|
+
if isinstance(event, dict) and event.get("type") == "assistant":
|
|
163
|
+
msg = event.get("message", {})
|
|
164
|
+
if isinstance(msg, dict):
|
|
165
|
+
model = msg.get("model")
|
|
166
|
+
if model:
|
|
167
|
+
return model
|
|
168
|
+
return None
|
|
169
|
+
|
|
170
|
+
def _extract_repo(self, events: list[dict]) -> Optional[str]:
|
|
171
|
+
"""Extract repo/branch info from attachment events."""
|
|
172
|
+
for event in events:
|
|
173
|
+
if isinstance(event, dict) and event.get("type") == "attachment":
|
|
174
|
+
git_branch = event.get("gitBranch")
|
|
175
|
+
if git_branch:
|
|
176
|
+
return git_branch
|
|
177
|
+
return None
|
|
178
|
+
|
|
179
|
+
def _extract_cwd(self, events: list[dict]) -> Optional[str]:
|
|
180
|
+
"""Extract current working directory."""
|
|
181
|
+
for event in events:
|
|
182
|
+
if isinstance(event, dict) and event.get("type") == "attachment":
|
|
183
|
+
cwd = event.get("cwd")
|
|
184
|
+
if cwd:
|
|
185
|
+
return cwd
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
def _extract_tool_calls(self, events: list[dict]) -> list[ToolCallRecord]:
|
|
189
|
+
"""Extract all tool_use items from assistant messages."""
|
|
190
|
+
tool_calls = []
|
|
191
|
+
for event in events:
|
|
192
|
+
if not isinstance(event, dict) or event.get("type") != "assistant":
|
|
193
|
+
continue
|
|
194
|
+
msg = event.get("message", {})
|
|
195
|
+
if not isinstance(msg, dict):
|
|
196
|
+
continue
|
|
197
|
+
for content_item in msg.get("content", []):
|
|
198
|
+
if isinstance(content_item, dict) and content_item.get("type") == "tool_use":
|
|
199
|
+
tool_calls.append(ToolCallRecord(
|
|
200
|
+
id=content_item.get("id", ""),
|
|
201
|
+
name=content_item.get("name", ""),
|
|
202
|
+
input_summary=str(content_item.get("input", ""))[:200],
|
|
203
|
+
))
|
|
204
|
+
return tool_calls
|
|
205
|
+
|
|
206
|
+
def _extract_files_touched(self, events: list[dict]) -> list[FileTouchRecord]:
|
|
207
|
+
"""Extract file operations from tool_use results (simplified)."""
|
|
208
|
+
files = []
|
|
209
|
+
for event in events:
|
|
210
|
+
if not isinstance(event, dict) or event.get("type") != "user":
|
|
211
|
+
continue
|
|
212
|
+
msg = event.get("message", {})
|
|
213
|
+
if not isinstance(msg, dict):
|
|
214
|
+
continue
|
|
215
|
+
for content_item in msg.get("content", []):
|
|
216
|
+
if isinstance(content_item, dict) and content_item.get("type") == "tool_result":
|
|
217
|
+
# Could parse file paths from result, but simplified for MVP
|
|
218
|
+
pass
|
|
219
|
+
return files
|
|
220
|
+
|
|
221
|
+
def _extract_metrics(self, events: list[dict]) -> RunMetrics:
|
|
222
|
+
"""Aggregate token usage across all assistant messages."""
|
|
223
|
+
total_input = total_output = total_cache = 0
|
|
224
|
+
for event in events:
|
|
225
|
+
if not isinstance(event, dict) or event.get("type") != "assistant":
|
|
226
|
+
continue
|
|
227
|
+
msg = event.get("message", {})
|
|
228
|
+
if not isinstance(msg, dict):
|
|
229
|
+
continue
|
|
230
|
+
usage = msg.get("usage", {})
|
|
231
|
+
if isinstance(usage, dict):
|
|
232
|
+
total_input += usage.get("input_tokens", 0)
|
|
233
|
+
total_output += usage.get("output_tokens", 0)
|
|
234
|
+
total_cache += usage.get("cache_read_input_tokens", 0)
|
|
235
|
+
|
|
236
|
+
return RunMetrics(
|
|
237
|
+
input_tokens=total_input if total_input > 0 else None,
|
|
238
|
+
output_tokens=total_output if total_output > 0 else None,
|
|
239
|
+
cache_tokens=total_cache if total_cache > 0 else None,
|
|
240
|
+
tool_call_count=len(self._extract_tool_calls(events)),
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
def _extract_errors(self, events: list[dict]) -> list[dict]:
|
|
244
|
+
"""Extract errors from system or tool_result events."""
|
|
245
|
+
errors = []
|
|
246
|
+
for event in events:
|
|
247
|
+
if not isinstance(event, dict):
|
|
248
|
+
continue
|
|
249
|
+
if event.get("type") == "system":
|
|
250
|
+
error = event.get("error")
|
|
251
|
+
if error:
|
|
252
|
+
errors.append({
|
|
253
|
+
"signature": error[:100],
|
|
254
|
+
"message": error,
|
|
255
|
+
"stack_excerpt": None,
|
|
256
|
+
"count": 1,
|
|
257
|
+
})
|
|
258
|
+
return errors
|
|
259
|
+
|
|
260
|
+
def _infer_outcome(self, events: list[dict], errors: list[dict]) -> str:
|
|
261
|
+
"""Infer success/failure/partial from events."""
|
|
262
|
+
# Has system error → failure
|
|
263
|
+
if errors:
|
|
264
|
+
return "failure" if len(errors) > 1 else "partial"
|
|
265
|
+
|
|
266
|
+
# Check for successful completion
|
|
267
|
+
for event in events:
|
|
268
|
+
if not isinstance(event, dict):
|
|
269
|
+
continue
|
|
270
|
+
if event.get("type") == "assistant":
|
|
271
|
+
msg = event.get("message", {})
|
|
272
|
+
if isinstance(msg, dict):
|
|
273
|
+
stop_reason = msg.get("stop_reason")
|
|
274
|
+
if stop_reason == "end_turn":
|
|
275
|
+
return "success"
|
|
276
|
+
|
|
277
|
+
return "unknown"
|