megaHarness / ARCHITECTURE.md
smlflg's picture
Initial public upload from Projekte/megaHarness
638dca1 verified
|
Raw History Blame Contribute Delete
16.7 kB
# megaHarness β€” Architektur-Plan
**Status:** Architektur-Lock fΓΌr 5-Tage-MVP (2026-04-23 β†’ 2026-04-28)
**Autor:** Samuel (Vision) + Claude/Opus 4.7 (Architektur-Synthese)
**Basis-Dokumente:** `idea` (Vision), `HarnessEcosystem/docs/gpt5-4-shift-report.md` (empirische Rechtfertigung)
---
## 0. North Star
megaHarness ist Samuels persΓΆnliches **Meta-Harness**: eine Schicht **ΓΌber** existierenden Agent-Harnesses (Claude Code, OpenClaude, Codex, OpenHands, Cursor, …), die sie als austauschbare Execution-Engines orchestriert. Der Wert liegt nicht in einem neuen Agent, sondern in **Komposition**: gleiche Task lΓ€uft auf anderem Harness + anderem Modell, ohne Re-Konfiguration.
Die acht Prinzipien aus `idea` sind nicht verhandelbar. Alles andere ist Implementierungsdetail.
---
## 1. Architektur in Schichten
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ L4 β€” UI-Layer β”‚
β”‚ Dashboard Β· Track-Viewer Β· MD-DB-Browser Β· Eval-Viewer β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ L3 β€” Kernel (megaHarness-Core) β”‚
β”‚ Task-Router Β· Parallel-Orchestrator Β· Sidecar-Engine β”‚
β”‚ Eval-Engine Β· MD-Resolver Β· Harness-Swap β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ L2 β€” MD-Datenbank (Source of Truth) β”‚
β”‚ projects/ Β· instructions/ Β· skills/ Β· tracks/ Β· evals/ β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ L1 β€” Harness-Adapter-Layer β”‚
β”‚ Claude-Code Β· OpenClaude Β· Codex Β· OpenHands Β· Hermes β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ L0 β€” Provider-Layer (extern, nicht megaHarness) β”‚
β”‚ Anthropic Β· OpenAI Β· Google Β· MiniMax Β· lokale Modelle β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
**Kern-Invariante:** L3 kennt L1 nur durch Adapter-Interface, L2 nur durch Resolver-Interface, L0 nie direkt. So wird Modell-Swap und Harness-Swap zur Config-Γ„nderung, nicht zum Refactor.
---
## 2. Kern-Komponenten
### 2.1 MD-Datenbank (L2)
**Rolle:** Einzige Quelle der Wahrheit fΓΌr alle adaptiven VertrΓ€ge.
**EntitΓ€ten:**
- `projects/*.md` β€” Projekt-Briefs, Done-Kriterien, Scope-Locks
- `instructions/*.md` β€” CLAUDE.md-Γ„quivalente, per Harness + Modell versioniert
- `skills/*.md` β€” wiederverwendbare Skill-Definitionen
- `sidecar/*.md` β€” Regelwerke (ADHS-Hooks, Scope-Guards, Commit-Gates)
- `tracks/*.md` β€” Live-Track-Definitionen (Task, Harness, Modell, Budget, Done)
- `evals/*.jsonl` β€” Eval-LΓ€ufe, append-only
**AdaptivitΓ€t:** jedes MD-File hat Frontmatter mit `applies_when:`-Clauses (Harness-ID, Modell-ID, Projekt-ID, Session-Phase). Der **MD-Resolver** (L3) wΓ€hlt zur Laufzeit das relevante Subset. Nicht-adaptive .md-Files sind Legacy-Schicht.
**Warum Markdown + Frontmatter, nicht SQLite/Postgres:**
- Menschenlesbar, Git-diffbar
- LLM-nativ (kein Query-Layer nΓΆtig fΓΌr Konsumption)
- Versionierbar mit dem Repo
- Zero Infrastruktur, keine Migrations-Drama
**Trade-off:** keine komplexen Joins, keine Transaktionen. FΓΌr diesen Use-Case egal.
### 2.2 Harness-Adapter-Protokoll (L1↔L3-Vertrag)
Jeder Harness-Adapter implementiert ein minimales Interface:
| Method | Zweck |
|---|---|
| `spawn(track_md)` | Starte Session aus Track-MD |
| `status(session_id)` | Lebens-Check, Tokens, Turn-Count |
| `interrupt(session_id)` | Hartes Stop |
| `collect(session_id)` | Transcript + Metriken holen |
| `capabilities()` | Was kann der Harness (Tools, Background, Worktrees) |
**Completion-Contract:** jeder Spawn bekommt aus der MD-DB eine explizite `done_when:`-Clause injiziert. Harnesses ohne native Contract-UnterstΓΌtzung (GPT-5.4 im Claude-Code-Harness: siehe Shift-Report) kriegen einen Wrapper-Prompt, der die Clause als System-Message voranstellt.
**Der Harness-Swap-Moment:** Swap = Track-MD unverΓ€ndert lassen, nur `harness_id:` im Frontmatter Γ€ndern. Re-Spawn. Der Kernel liefert dieselben Inputs.
### 2.3 Task-Router (L3)
**Input:** Task-Request (aus UI, CLI, Cron oder Eval-Trigger)
**Output:** Track-MD + Harness-Auswahl
**Routing-Logik:**
1. Matching: welche Harnesses + Modelle sind kompatibel mit Task-Typ
2. Policy: Default-Modell pro Task-Typ aus `instructions/router-policy.md`
3. Override: explizite User-Wahl schlΓ€gt Policy
4. Fallback: wenn PrimΓ€r-Harness unavailable, SekundΓ€r aus Policy
**Empirisch kalibriert:** Shift-Report zeigt, dass GPT-5.4 im Claude-Code-Harness 2–8M Input-Tokens pro Session verbrennt. Router-Policy verhindert diese Kombination by default, es sei denn explizit als Experiment deklariert.
### 2.4 Parallel-Orchestrator (L3)
**Rolle:** N Tracks gleichzeitig, keine Race Conditions im Dateisystem, Checkpoint-fΓ€hig.
**Mechanismen:**
- Git-Worktree pro Track (Isolation auf Repo-Ebene)
- tmux/supervisord fΓΌr Prozess-Leben (keine eigene Prozess-Verwaltung bauen)
- MD-Queue fΓΌr Track-Slots (`tracks/active/`, `tracks/queued/`, `tracks/done/`, `tracks/failed/`)
- Heartbeat-File pro Track fΓΌr Status-Polling
**KapazitΓ€t:** 3–5 Tracks parallel. Mehr ist Token-Verbrennung ohne Kognitions-Nutzen (Samuel kann nicht 8 parallel reviewen).
### 2.5 Sidecar-Engine (L3)
**Rolle:** Samuel-spezifische Kalibrierung β€” ADHS-Guards, Scope-Warnungen, Commit-Gates.
**Baut auf:** existierendem `Sidecar-ng`-Projekt (bereits produktiv, liefert die Hook-Payloads die dieser Dialog durchgehend zeigt).
**Integration:** Sidecar-Engine ist **kein neuer Code**, sondern ein Adapter der existierende Sidecar-NG-Events an die MD-DB und den Orchestrator sendet. Regeln kommen aus `sidecar/*.md`.
**Kernfunktion fΓΌr megaHarness:** Cross-Track-Scope-Guard. Wenn Track A in `home/` arbeitet und Track B plΓΆtzlich auch: Flag.
### 2.6 Eval-Engine (L3)
**Rolle:** jeder Track misst sich selbst.
**Baut auf:** existierendem `HarnessEcosystem/sidebyside` (liefert bereits snapshot-basierte Vergleiche, siehe Shift-Report).
**Metriken pro Track:**
- Token-Effizienz (in/out, pro Turn)
- Tool-Burst-Dichte (Tool-Calls pro Turn)
- Contract-AdhΓ€renz (Done-Clause erreicht?)
- Termination-Typ (clean / limit / interrupt / crash)
- Outcome-Label (manuell oder durch Review-Track)
**Feedback-Loop:** Eval-Ergebnisse schreiben zurΓΌck nach `evals/*.jsonl`. Router-Policy konsumiert aggregierte Evals β†’ empirische Modell-Auswahl.
### 2.7 UI-Layer (L4)
**Kern-Views:**
1. Track-Dashboard (welche Tracks laufen, Status, ETA, Tokens)
2. MD-DB-Browser (Navigation + Diff)
3. Eval-Viewer (Baut auf `frontier-llm-harness`-Γ„sthetik auf)
4. Spawn-Composer (Track-MD erstellen β†’ Router β†’ Adapter)
**Technologie-Entscheidung:** statische SPA + lokaler HTTP-Server, liest direkt aus `tracks/` + `evals/`. Kein Backend. Grund: `sidebyside` + `frontier-llm-harness` haben das Pattern bereits bewiesen, keine neue Infrastruktur.
**Live-Updates:** Polling (nicht WebSocket). KISS.
---
## 3. Bausteine-Map (Was existiert, was fehlt)
| Schicht / Komponente | Existierend (βœ“) / Fehlt (βœ—) | Quelle |
|---|---|---|
| L2 MD-DB Schema | βœ— | β€” |
| L2 MD-Resolver | βœ— | β€” |
| L2 Adaptive Regeln existierend | (βœ“) teilweise | PromptGarage, Skills |
| L1 Claude Code Adapter | (βœ“) implizit (JSONL-Logs) | `~/.claude/projects/` |
| L1 Codex/GPT-5.4 Adapter | (βœ“) implizit | `extract_codex.py` |
| L1 OpenClaude Adapter | βœ— | Fork existiert, kein Adapter |
| L1 Hermes Adapter | (βœ“) teilweise | `extract_hermes.py` |
| L1 OpenHands Adapter | βœ— | β€” |
| L3 Harness-Swap Mechanik | (in Arbeit) | `derWolfimSchafspelz/openclaude` |
| L3 Task-Router | βœ— | β€” |
| L3 Parallel-Orchestrator | βœ— | β€” |
| L3 Sidecar-Engine | βœ“ | `Sidecar-ng` |
| L3 Eval-Engine | βœ“ | `HarnessEcosystem/sidebyside` |
| L4 Dashboard | (βœ“) Aesthetik + Pattern | `SidecarDashboard`, `KomandoZentral`, `frontier-llm-harness` |
**SchlΓΌssel-Erkenntnis:** L2 (MD-DB) ist der kritische neue Baustein. L3-Kernel ist dΓΌnne Integration existierender Teile. L1-Adapter sind jeweils 1–2 Tage Arbeit, wir brauchen in 5 Tagen nur 2–3.
---
## 4. Harness-Swap β€” der aktuelle Build
**Definition:** Harness-Swap ist der Mechanismus, der denselben Task auf einem anderen Harness re-exekutiert, ohne Task-Definition zu Γ€ndern.
**Architekturrolle:** Harness-Swap ist **nicht** ein L1-Adapter. Es ist ein L3-Kernel-Feature, das L1-Adapter koordiniert.
**Interface:**
```
swap(track_id, from_harness, to_harness) β†’
1. collect(from_harness.session) β†’ transcript + state
2. translate(state, to_harness.capabilities) β†’ new_state
3. track_md.harness_id = to_harness
4. spawn(to_harness, track_md, continuation=new_state)
```
**State-Translation-Regeln** sind in `instructions/harness-translation-*.md` abgelegt (eine Datei pro Harness-Paar). Diese Regeln sind **adaptiv** β€” sie werden basierend auf Eval-Daten (was hat funktioniert beim letzten Swap?) fortgeschrieben.
**MVP-Umfang:** Claude Code ↔ OpenClaude Swap. Alles andere Post-MVP.
---
## 5. Datenfluss β€” der eine zentrale Loop
```
User-Intent
↓
MD-Resolver liest projects/ + instructions/
↓
Task-Router wΓ€hlt Harness + Modell (Policy + Eval-History)
↓
Track-MD geschrieben in tracks/active/
↓
Parallel-Orchestrator spawnt via L1-Adapter
↓
Harness lΓ€uft (mit Completion-Contract injiziert)
↓
Sidecar-Engine beobachtet, flagt bei Regel-Verletzung
↓
Abschluss: Eval-Engine schreibt nach evals/*.jsonl
↓
Track-MD nach tracks/done/ verschoben
↓
UI reflektiert neuen Zustand
↓
Router-Policy lernt aus evals/ fΓΌr nΓ€chsten Spawn
```
Dieser Loop ist das System. Alles andere ist Verzierung.
---
## 6. 5-Tage-Meilensteine (architektonisch)
Jeder Meilenstein hat **eine binΓ€re Done-Frage**, nicht eine Feature-Liste.
### Tag 1 β€” Fundament (2026-04-23)
**Done-Frage:** Existiert `md-db/` mit Schema-definierten Frontmatter-Keys, und kann der MD-Resolver aus einer `tracks/example.md` eine zusammengesetzte Instruction produzieren?
- MD-DB-Schema finalisiert (Frontmatter-Felder, Ordner-Layout)
- MD-Resolver als dΓΌnner Layer
- Ein Beispiel-Track in der DB abgelegt
- **Non-Goal Tag 1:** kein Spawn, keine UI, kein Router
### Tag 2 β€” Execution (2026-04-24)
**Done-Frage:** Kann ein Track-MD via Adapter einen Claude-Code-Subprozess spawnen, laufen lassen, und das Transcript ingesten?
- L1-Adapter: Claude Code (via CLI-Spawn)
- L1-Adapter: OpenClaude (via Fork-CLI)
- L3 Spawn-Funktion im Kernel
- **Non-Goal:** kein Parallelismus, kein Swap, kein Router
### Tag 3 β€” ParallelitΓ€t + Router (2026-04-25)
**Done-Frage:** Laufen 3 Tracks gleichzeitig in Worktrees, ohne dass sie sich im Dateisystem zerstΓΆren, und wΓ€hlt der Router automatisch Harness+Modell aus der Policy?
- Parallel-Orchestrator mit Worktree-Isolation
- Task-Router mit statischer Policy (Eval-Feedback Post-MVP)
- Heartbeat + Status-Polling
- **Non-Goal:** UI, Swap
### Tag 4 β€” Swap + Eval-Integration (2026-04-26)
**Done-Frage:** Kann ein laufender Track von Claude Code nach OpenClaude geswapt werden, und schreibt der Eval-Hook nach Abschluss saubere Metriken in `evals/`?
- Harness-Swap (MVP: Claude Code ↔ OpenClaude)
- Eval-Engine-Hook an Adapter-Collection angebunden
- `sidebyside`-Scripts als Eval-Konsumenten integriert
- **Non-Goal:** UI, Router-Lernen aus Evals
### Tag 5 β€” UI + E2E (2026-04-27, Puffer 2026-04-28)
**Done-Frage:** Sieht Samuel im Browser ein Track-Dashboard, kann er einen neuen Track spawnen und das Ergebnis inklusive Evals einsehen?
- Statische SPA mit Track-Dashboard + MD-DB-Browser + Eval-Viewer
- Spawn-Composer (einfache Form, kein Advanced)
- Ein echter E2E-Run: Spawn β†’ Parallel β†’ Swap β†’ Eval β†’ UI
- Puffer-Tag (28.04) fΓΌr Polish und unerwartete Blocker
---
## 7. Risiken & Mitigationen
| Risiko | Wahrscheinlichkeit | Impact | Mitigation |
|---|---|---|---|
| Scope-Creep ΓΌber MVP hinaus | Hoch | Hoch | Jeder Tag hat eine binΓ€re Done-Frage, nicht Feature-Liste. Post-MVP-Liste explizit in Β§9. |
| GPT-5.4 im Claude-Code-Harness verbrennt Token-Budget | Hoch | Mittel | Router-Policy verhindert Kombination by default. Nur als explizites Experiment. Empirisch belegt durch Shift-Report. |
| UI-Tag-5 wird zum Zeitfresser | Hoch | Hoch | Statische SPA, keine neue Infrastruktur. `frontier-llm-harness` als Muster. Kein Framework-Neuwahl. |
| MD-DB-Schema wird zu komplex | Mittel | Hoch | Schema ≀ 10 Frontmatter-Keys im MVP. Erweiterung nur mit belegtem Use-Case. |
| Parallelismus zerstârt Dateisystem | Mittel | Hoch | Git-Worktree pro Track. Kein Shared-State außerhalb `md-db/`. |
| Bestehende Projekte nicht sauber integrierbar | Mittel | Mittel | MVP nutzt nur `Sidecar-ng` und `sidebyside` als Integration. Rest Post-MVP. |
| 5-Tage-SchΓ€tzung zu optimistisch | Hoch | Hoch | Tag 5 hat Puffer 28.04. MVP-Scope bewusst klein. Wenn Tag 3 nicht done: Swap+Eval gehen Post-MVP. |
| ADHS-Fokus-Kollaps | Mittel | Hoch | Sidecar-NG aktiv, tΓ€gliche Done-Frage als Anker, keine Parallelarbeit an mehr als EINEM Kernel-Teil gleichzeitig. |
---
## 8. Done-Kriterien (Tag 5)
Der MVP ist fertig, wenn **alle** folgenden Bedingungen wahr sind:
1. `md-db/` existiert mit den definierten Ordnern
2. Mindestens 2 Harness-Adapter funktionieren (Claude Code, OpenClaude)
3. 3 Tracks sind parallel gelaufen ohne gegenseitige Blockade
4. Ein Harness-Swap wurde erfolgreich durchgefΓΌhrt (Claude Code β†’ OpenClaude)
5. Mindestens ein Eval-Lauf ist in `evals/` persistent
6. UI zeigt aktuelle Tracks + Evals korrekt
7. Ein Ende-zu-Ende-Flow (Spawn β†’ Parallel β†’ Swap β†’ Eval β†’ UI) lief ohne manuelle Eingriffe durch
Wenn 5 von 7 erreicht: **MVP accepted**. Wenn weniger: MVP-Scope reevaluieren, nicht verlΓ€ngern.
---
## 9. Non-Goals (Post-MVP, bewusst ausgeschlossen)
- Cursor-Adapter
- OpenHands-Adapter
- Hermes-Adapter (Collect-Script reicht)
- Router-Policy-Lernen aus Eval-History
- Advanced Spawn-Composer in UI (Form-only reicht)
- Fremde Repos als Tracks (nur eigene im MVP)
- Cloud-Deployment
- Multi-User
- Auth
- Mobile-UI
- Persistente DB (MD-Files reichen)
- Config-Hot-Reload
- Skill-Marketplace
- Eval-Auto-Labeling durch Review-Track
Jeder dieser Punkte ist ein legitimes Feature β€” aber nicht in 5 Tagen.
---
## 10. Glossar
- **Harness**: AusfΓΌhrungsumgebung fΓΌr einen Agent (Claude Code, Codex, OpenHands …)
- **Modell**: LLM-Endpoint (Opus, GPT-5.4, …)
- **Track**: Eine konkrete Task-Instanz mit Harness + Modell + Projekt-Kontext
- **Spawn**: Track in einem Harness starten
- **Swap**: Track mitten im Leben auf anderen Harness ΓΌbertragen
- **MD-DB**: Markdown-basierte Datenbank (L2)
- **Completion-Contract**: Explizites `done_when:` in Track-MD
- **Adaptiv**: .md-File gilt nur wenn Frontmatter-`applies_when:` zur Laufzeit matcht
---
## 11. Offene Architektur-Fragen (vor Tag 1 zu entscheiden)
1. **Kernel-Sprache:** Python (ΓΆkosystemnah zu Claude Code + Codex) vs TypeScript (nΓ€her an UI). **Empfehlung: Python**, Grund: alle existierenden Scripts (`extract_*.py`, `build_snapshot.py`) sind Python. Kein Sprach-Bruch.
2. **Prozess-Modell:** tmux vs supervisord vs systemd-user. **Empfehlung: tmux**, Grund: Samuel nutzt es bereits, minimal neues Setup.
3. **UI-Framework:** vanilla JS (wie `sidebyside`) vs Preact vs Svelte. **Empfehlung: vanilla**, Grund: `sidebyside` + `frontier-llm-harness` sind vanilla und lesbar.
4. **MD-DB-Location:** `~/.megaharness/md-db/` vs im Repo. **Empfehlung: im Repo** (`megaHarness/md-db/`), Grund: Git-versioniert, portabel, diffbar.
---
**Dieser Plan ist ein Vertrag zwischen Samuel und dem 5-Tage-Ich. Jede Abweichung muss als ADR (Architecture Decision Record) in `docs/adr/` dokumentiert werden β€” oder explizit abgelehnt und hier gestrichen. Keine stille Scope-Drift.**