commit efee259d01e7e3f0cc3bdf88905a1398967ed8c2 Author: Tarik Moussa Date: Wed Jun 3 06:55:39 2026 +0200 feat: bootstrap jetson-ai-ollama from agent-swarm template Leader-Bootstrap (Planung) aus Template + Jetson-Meta-Prompt: - ROADMAP-Board W1-W6 als Abhaengigkeits-DAG (Ready-Set = {W1}) - STATE mit disjunkter Datei-Ownership W2-W6 - CONVENTIONS Projekt-Vertrag (Profile, Pfade, Ports, Daemon-Env, num_ctx, DVC, Scope) - manifests/requirements.md = kalt verifizierbares Review-Manifest (R-01..R-10) - REVIEW.md Kalt-Review-Einstieg; ADR 0002 (Ollama-nativ, kein Swapper/Gateway) - session-prompts/W1..W6 dispatch-fertig; .gitignore um Jetson-Ignores erweitert - examples/walkthrough entfernt (Projekt hat eigenes gefuelltes Board) Co-Authored-By: Claude Opus 4.8 diff --git a/.github/workflows/gates.yml b/.github/workflows/gates.yml new file mode 100644 index 0000000..c850226 --- /dev/null +++ b/.github/workflows/gates.yml @@ -0,0 +1,16 @@ +name: gates +on: [push, pull_request] +jobs: + quality: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: { fetch-depth: 0 } + - name: Session-Hygiene-Gate + run: bash scripts/gate-session-hygiene.sh + - name: Ownership-Gate + run: bash scripts/gate-ownership.sh + - name: Doku-Drift-Gate + run: bash scripts/gate-doc-drift.sh + - name: Metriken sammeln + run: bash scripts/metrics.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ba2047 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +__pycache__/ +*.py[cod] +.venv/ +.env +*.log +logs/ +.DS_Store +.idea/ +.vscode/ +# metrics/*.csv wird bewusst getrackt — die Observability-Story braucht den Trend. + +# --- Jetson AI / Ollama spezifisch --- +*.gguf +models/ +.dvc/cache/ +.dvc/tmp/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..58ecdbb --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,38 @@ +# AGENTS.md — Einstiegspunkt für jede Session + +> **Lies dies zuerst. Lies NICHT das ganze Repo.** Orientiere dich in dieser +> Reihenfolge und höre auf, sobald du genug Kontext für deine Aufgabe hast. + +## Lese-Reihenfolge (klarer Start) +1. **Dieses Dokument** — wer macht was, wo steht was. +2. **`STATE.md`** — *wo wir gerade stehen* (Now / In Progress / Blocked / Next / + offene Audit-Findings). Die einzige Quelle für den aktuellen Stand. +3. **`CONVENTIONS.md`** — verbindliche Regeln (Naming, Pfade, Commits, Ownership, + Model-Attribution, Review-Gate). +4. **Deine Rollen-Datei** — `docs/roles/{leader,worker,reviewer}.md`. + Welches Modell für welche Arbeit: `docs/roles/model-routing.md`. +5. **Die relevante Loop-Datei** — `docs/loops/{feature,audit}-loop.md`. + Bei Research-Items: `docs/loops/spike-gate.md`. +6. **Dein Session-Prompt** — `session-prompts/` (fertig ausgefüllter Prompt für + diese Session — kein Lesen des ganzen Repos nötig). +7. Nur bei Bedarf: `manifests/requirements.md`, betroffene ADRs, Code. + +## Wo finde ich was? +| Frage | Datei | +|---|---| +| Aktueller Stand / nächster Schritt | `STATE.md` | +| Regeln & gemeinsamer Vertrag | `CONVENTIONS.md` | +| Plan / Board / Ready-Set (DAG) | `ROADMAP.md` | +| Befülltes Beispiel zum Lernen | `examples/walkthrough/` | +| Warum wurde X so entschieden | `docs/adr/` | +| Anforderung → Datei → Test → Status | `manifests/requirements.md` | +| Was hat die letzte Session getan | `sessions/` (neuester Eintrag) | +| Offene Prüf-Befunde + Model-Zuweisung | `audits/` | +| Welches Modell für welche Arbeit | `docs/roles/model-routing.md` | +| Kaltstartfähige Session-Prompts | `session-prompts/` | +| Token-Kosten kontrollieren | `docs/token-hygiene.md` | + +## Pflicht am Session-Ende +- `STATE.md` aktualisieren · Session-Log aus `sessions/TEMPLATE.md` anlegen + (inkl. **Token-Verbrauch** + Model-Attribution) · betroffene Manifeste/Docs anpassen · + Quality-Gate ausführen (`scripts/gate-session-hygiene.sh`). diff --git a/CONVENTIONS.md b/CONVENTIONS.md new file mode 100644 index 0000000..b1661e6 --- /dev/null +++ b/CONVENTIONS.md @@ -0,0 +1,64 @@ +# CONVENTIONS.md — gemeinsamer Vertrag + +Verbindlich für **alle** Aktoren. Änderungen nur per ADR. + +## Ownership +- **Kein Paket editiert Dateien eines anderen.** Integration & Konfliktlösung + ausschließlich durch den Leader. +- Jede Datei hat genau ein zuständiges Worker-Paket (siehe `STATE.md`). + +## Git & Commits +- Branch je Paket: `feat/`, `audit/`, `fix/`. +- **Conventional Commits:** `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, + `chore:`. Der Git-Log ist Teil der Dokumentation. +- **Model-Attribution:** jeder Commit eines Agenten enthält einen Trailer: + `Co-Authored-By: Claude ` + Tier = Capability-Bezeichnung des eingesetzten Modells, z. B. „Sonnet 4.6" + für mittlere Kapazität oder „Opus 4.8" für maximale — nicht der interne + Modell-Name. Gilt für das zum Commit-Zeitpunkt eingesetzte Modell. + Ermöglicht nachträgliche Rückverfolgung welche Kapazitätsstufe was entschieden hat. + +## Review-Gate +- **Jede Implement-Session wird von einer separaten high-capacity-Session reviewed** + (aktuell: Opus-Tier). Der Review läuft kalt (eigene Session, kein Vorkontext), + prüft den Diff, und gibt APPROVE oder CHANGES-REQUESTED zurück. +- Implement-Kapazitätsstufe ≠ Review-Kapazitätsstufe: ein Modell, das sich selbst + reviewed, findet systematisch weniger als ein unabhängiger Pass auf höchster Stufe. +- Konkrete Tier-Zuordnungen: `docs/roles/model-routing.md`. +- Review-Gate-Checkliste: `docs/roles/reviewer.md`. + +## Dokumentation +- **Single Source of Truth** je Information — keine Duplikate über Docs hinweg. +- Doku ist knapp: ein Dokument, das man nicht mehr liest, driftet. Größenbudget + pro Doc beachten (Faustregel < 200 Zeilen). +- Jede Code-Änderung passt das passende Doc + Manifest **in derselben Session** an. + +## Definition of Done +1. Manifest-Eintrag (`manifests/requirements.md`) mit Test + Status `done`. +2. Tests grün. 3. Docs aktuell. 4. `STATE.md` aktualisiert. +5. Session-Log geschrieben. 6. Quality-Gate `PASS`. + +## Projekt-Vertrag: Jetson AI / Ollama +Verbindlich für alle Worker — Single Source of Truth dieser Werte. Änderungen nur per ADR. + +- **Hardware:** Jetson Orin Nano Super 8 GB (~7,4 GB nutzbar). Single-User → latenz-, + nicht durchsatzgebunden. Kein Batching, keine Inferenz-Skalierung. +- **Profilnamen (Ollama-Modellnamen):** `qwen-light`, `gemma`, `qwen-heavy`. +- **Pfade:** GGUF unter `/opt/jetson-ai/models/.gguf`; Ollama-Store + `/opt/ollama/models` (nur Laufzeit-Cache). +- **Ports / Endpoints:** Ollama `11434` (OpenAI `/v1/chat/completions`, Status + `/api/ps`); Exporter `/metrics` auf Port `8000`. +- **Daemon-Env (in `ollama/systemd/ollama.service.d/override.conf`):** + `OLLAMA_FLASH_ATTENTION=1`, `OLLAMA_KV_CACHE_TYPE=q8_0`, + `OLLAMA_MAX_LOADED_MODELS=1` (genau ein Modell resident, 8-GB-Schutz), + `OLLAMA_KEEP_ALIVE=30s`, `OLLAMA_MODELS=/opt/ollama/models`, + `OLLAMA_HOST=0.0.0.0:11434` (nur LAN, Firewall auf den Proxy beschränken). +- **`num_ctx` je Modelfile explizit** (Ollama kürzt sonst still): light/gemma 16384, + heavy 8192. +- **Env-Variablen Single Source:** `.env.example` — nur Platzhalter, **nie Secrets**. +- **DVC = Modell-Source-of-Truth.** `build-models.sh` baut alle drei Profile + reproduzierbar aus den DVC-getrackten GGUFs. +- **Scope-Grenze (out of repo):** nginx-Reverse-Proxy (TLS + OAuth) und + Prometheus/Grafana laufen **off-box**. Ollama hat **keine eigene Auth** → nie + direkt ins Internet binden. +- **Code:** Type Hints, Docstrings. diff --git a/README.md b/README.md new file mode 100644 index 0000000..64d04b8 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# Jetson AI / Ollama (MLOps) + +Lokal laufendes **Single-User-AI-System** auf einem **Jetson Orin Nano Super (8 GB)**: +Ollama-Daemon serviert drei Modell-Profile (OpenAI-kompatibel), ein schlanker +Exporter-Sidecar exponiert `/metrics`. Modellwechsel passiert **nativ über den +Modellnamen** — kein eigener Swapper, kein Gateway (siehe `docs/adr/0002-ollama-native.md`). + +- **Profile:** `qwen-light` (Daily-Driver) · `gemma` (Creative/Chat, multimodal) · + `qwen-heavy` (harte Reasoning-Fälle). `OLLAMA_MAX_LOADED_MODELS=1` hält genau ein + Modell resident → drei Profile sind quasi gratis. +- **Optimierung:** `q8_0`-KV-Cache + Flash Attention, `num_ctx` je Profil explizit. +- **Daten:** DVC ist Modell-Source-of-Truth; Ollamas Blob-Store nur Laufzeit-Cache. + +> **Scope:** Dieses Repo deckt **nur den Jetson** ab. nginx (TLS + OAuth) und +> Prometheus/Grafana laufen off-box. Ollama hat keine eigene Auth → nur ans LAN +> binden, Firewall auf den Proxy. Voller Vertrag: [`CONVENTIONS.md`](CONVENTIONS.md). + +--- + +## Arbeitsmodell (agent-swarm) +Dieses Repo wurde aus dem **agent-swarm-Template** gebootstrapt: ein Leader/Worker- +Agentensystem, dessen Stand komplett auf Disk lebt — kalt lesbar ohne Vorkontext. +Methodik: [`docs/methodology.md`](docs/methodology.md) · Herkunft: +[`docs/about-template.md`](docs/about-template.md). + +| Wo | Datei | +|---|---| +| Stand & nächster Schritt | [`STATE.md`](STATE.md) | +| Plan / Board / Ready-Set (DAG) | [`ROADMAP.md`](ROADMAP.md) | +| Gemeinsamer Vertrag | [`CONVENTIONS.md`](CONVENTIONS.md) | +| Kalt-Review-Einstieg | [`REVIEW.md`](REVIEW.md) | +| Dispatch-fertige Worker-Prompts | [`session-prompts/`](session-prompts/) | + +## Sofort bauen +Die Planung ist fertig (W1–W6 im Board). So baust du es: + +1. **W1 zuerst** — frische Session öffnen, Modell **Sonnet**, Inhalt von + [`session-prompts/W1.md`](session-prompts/W1.md) einfügen → legt das Grundgerüst an. +2. **Review-Gate** (Opus, kalt) → mergen → W1 im Board auf `✅`. +3. **W2–W5 parallel** — je eigene Session (`session-prompts/W2.md` … `W5.md`), + disjunkte Datei-Ownership, laufen unabhängig. +4. **W6 zuletzt** — Docs, integriert die Realität der anderen Pakete. + +Jeder Worker-Prompt ist self-contained (Modell, Branch, Dateien, Akzeptanzkriterien, +Abschluss-Gates). Die Gates (`scripts/gate-*.sh`) sind aktiv und prüfen Ownership, +Hygiene und Doku-Drift bei jedem Schritt. diff --git a/REVIEW.md b/REVIEW.md new file mode 100644 index 0000000..c4c43c3 --- /dev/null +++ b/REVIEW.md @@ -0,0 +1,29 @@ +# REVIEW — Kalt-Review-Einstieg + +Dieses Repo ist so gebaut, dass ein Reviewer **ohne jeden Vorkontext** in einer +frischen Session verifizieren kann, ob alles stimmt. Du musst nichts glauben — +führe die Prüfbefehle aus. + +## In dieser Reihenfolge +1. **`AGENTS.md` → `STATE.md` → `CONVENTIONS.md`** lesen. Kannst du dich allein + damit orientieren? (Wenn nein → erstes Finding.) +2. **`manifests/requirements.md`** ist das Verifikations-Manifest: je Erfolgs- + kriterium eine Zeile *Anforderung → Datei(en) → Prüfbefehl → Status*. Gehe es + Zeile für Zeile durch und führe den Prüfbefehl jeder `done`-Zeile aus. +3. **Tests kodieren die Kriterien** (Modelfile-Build, Endpoint-Smoke) — ausführen + statt glauben: `pytest tests/ -q`. +4. **Git-Log** (Conventional Commits + Model-Attribution) erzählt die Reihenfolge. + +## Automatische Gates (lokal lauffähig) +```bash +bash scripts/gate-session-hygiene.sh # STATE/Session-Log/Commits sauber? +bash scripts/gate-ownership.sh # kein Cross-Editing über Paket-Grenzen? +bash scripts/gate-doc-drift.sh # done-Zeilen belegen ihre Dateien? +``` + +## Was „fertig" heißt +Alle Zeilen in `manifests/requirements.md` auf `done`, ihre Prüfbefehle grün, +`tests/` grün, die drei Gates `PASS`. Die Erfolgskriterien selbst stehen — Single +Source of Truth — im Manifest und in `CONVENTIONS.md` (Projekt-Vertrag), nicht hier. + +> Reviewer-Rolle und Checkliste im Detail: `docs/roles/reviewer.md`. diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..2cfc366 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,41 @@ +# ROADMAP — Board & Ready-Set (Jetson AI / Ollama) + +Eingang des Feature-Loops **und** der Abhängigkeits-DAG. Der Leader berechnet jeden +Zyklus das **Ready-Set** und dispatcht nur daraus. + +> **ROADMAP vs. STATE:** ROADMAP = der ganze geplante Graph. `STATE.md` = was +> *gerade jetzt* läuft. Item wandert: `🔲` → beim Dispatch in STATE „In Progress" → +> bei Merge zurück als `✅` in „Done". + +## Legende +- **Typ:** 🔌 port · 🔬 research · 🧱 infra +- **Status:** ✅ done · 🔲 ready · ⏸ blocked-by-prereq · ⛔ blocked-extern + +## Ready-Set-Regel +``` +Ready-Set = { Items mit 🔲, deren Prereqs ALLE ✅ } → aktuell: { W1 } +``` +1. Ready-Set bilden. 2. Modell aus `docs/roles/model-routing.md`. 3. Prompt aus +`session-prompts/.md`. 4. Worker bauen. 5. Review-Gate (hoch) → Merge → ✅. + +> **Dieses Projekt ist rein 🧱 infra/config** — kein 🔬-Item, daher kein Spike-Gate. +> Die Kopplung der Pakete läuft ausschließlich über `CONVENTIONS.md`. + +## Board +| ID | Item | Typ | Status | Prereqs | Rolle · Tier | Aufwand | +|----|------|-----|--------|---------|--------------|---------| +| W1 | Grundgerüst: Struktur, README-Skelett, LICENSE, `.gitignore`, `.env.example` | 🧱 | 🔲 | — | Worker · mittel | ~0.5 d | +| W2 | Ollama-Profile: Modelfiles light/gemma/heavy, systemd-override, `build-models.sh`, DVC | 🧱 | ⏸ | W1 | Worker · mittel | ~1 d | +| W3 | Exporter-Sidecar: `/metrics`:8000 + systemd-Service | 🧱 | ⏸ | W1 | Worker · mittel | ~0.5 d | +| W4 | Setup & CI/CD: `setup-jetson.sh`, `benchmark.sh`, Workflows | 🧱 | ⏸ | W1 | Worker · mittel | ~1 d | +| W5 | Client & Tests: `client/`, `tests/`, Requirements | 🧱 | ⏸ | W1 | Worker · mittel | ~1 d | +| W6 | Docs: architecture/api/deployment/troubleshooting + README-Finalisierung | 🧱 | ⏸ | W2,W3,W4,W5 | Scholar · klein | ~0.5 d | + +**Wellen:** W1 zuerst (alleine) → dann **W2–W5 parallel** (disjunkte Ownership, +nur über `CONVENTIONS.md` gekoppelt) → W6 zuletzt (integriert die Realität der +anderen). Session-Prompts liegen fertig unter `session-prompts/W1…W6.md`. + +## Done +| ID | Item | Session | Commit | +|----|------|---------|--------| +| — | _(noch nichts gemerged — W1 ist als nächstes dran)_ | — | — | diff --git a/STATE.md b/STATE.md new file mode 100644 index 0000000..fe60a14 --- /dev/null +++ b/STATE.md @@ -0,0 +1,35 @@ +# STATE — aktueller Stand (Jetson AI / Ollama) + +> Live-Ebene. Was *jetzt* läuft. Plan steht im Board (`ROADMAP.md`). + +**Letzte Session:** bootstrap / 2026-06-03 · **Aktive Rolle:** leader + +## Now (in dieser Session im Fokus) +- Bootstrap fertig (Planung). Nächster Dispatch: **W1 Grundgerüst** (`session-prompts/W1.md`). + +## In Progress (begonnen, nicht fertig) +- _(keine — alles geplant, noch nichts gebaut)_ + +## Blocked +- W2–W5 — warten auf W1 (Grundgerüst). `⏸` +- W6 (Docs) — wartet auf W2–W5. `⏸` + +## Next (priorisiert) +1. W1 dispatchen (Worker · mittel). +2. Nach W1-Merge: W2, W3, W4, W5 **parallel** dispatchen (disjunkte Ownership). +3. Zuletzt W6 (Scholar · klein). + +## Offene Audit-Findings +- _(keine — Projekt frisch gebootstrapt)_ + +## Datei-Ownership (aktiv) +> Verzeichnis-Pfade mit Slash beenden (das prüft `scripts/gate-ownership.sh`). +> W1 läuft sequentiell zuerst und legt das Grundgerüst an; ab dann gilt: + +| Paket | Dateien/Pfade | Owner | +|---|---|---| +| W2 | `ollama/`, `scripts/build-models.sh`, `.dvc/` | worker-w2 | +| W3 | `exporter/`, `requirements/exporter.txt` | worker-w3 | +| W4 | `scripts/setup-jetson.sh`, `scripts/benchmark.sh`, `.github/workflows/` | worker-w4 | +| W5 | `client/`, `tests/`, `requirements/client.txt`, `requirements/dev.txt` | worker-w5 | +| W6 | `docs/architecture.md`, `docs/api.md`, `docs/deployment.md`, `docs/troubleshooting.md` | worker-w6 | diff --git a/audits/README.md b/audits/README.md new file mode 100644 index 0000000..6559f39 --- /dev/null +++ b/audits/README.md @@ -0,0 +1,4 @@ +# audits/ + +Befunde des externen Reviewers: `YYYY-MM-DD-.md` aus `TEMPLATE.md`. +Jeder Befund mit Severity; Korrektur-Tasks wandern nach `ROADMAP.md`/`STATE.md`. diff --git a/audits/TEMPLATE.md b/audits/TEMPLATE.md new file mode 100644 index 0000000..5c5fcb7 --- /dev/null +++ b/audits/TEMPLATE.md @@ -0,0 +1,15 @@ +# Audit + +- **Reviewer-Session:** kalt (kein Vorkontext) +- **Orientierung allein aus AGENTS/STATE/CONVENTIONS gelungen?** Ja/Nein + +## Befunde +| # | Typ (drift/hygiene/untested) | Beschreibung | Severity | Korrektur-Task | +|---|------------------------------|--------------|----------|----------------| +| 1 | _…_ | _…_ | low/med/high | _Roadmap-/STATE-Eintrag_ | + +## Verifikation +- Manifest geprüft: _…_ · Tests ausgeführt: _… -> Ergebnis_ + +## Empfehlung +- _Audit-Loop weiter / Feature-Loop freigegeben._ diff --git a/docs/about-template.md b/docs/about-template.md new file mode 100644 index 0000000..a697ca3 --- /dev/null +++ b/docs/about-template.md @@ -0,0 +1,58 @@ +# agent-swarm-repo + +Ein **generelles Git-Repo-Template für KI-Agenten-Arbeit**. Das Repo ist die +*dauerhafte gemeinsame Erinnerung* — Sessions sind flüchtig, der Stand lebt in den +Dateien. Agenten koordinieren über Dateien, nicht über den Chat. + +## Aktoren & Modelle + +| Rolle | Modell | Aufgabe | +|---|---|---| +| Leader | Sonnet | Orchestrierung, Klassifikation, Integration | +| Worker / Porter | Sonnet | Implementierung mit klarer Spec, faithful Ports | +| Theorist | Opus | Formeln ableiten, Validation entwerfen | +| Prototyper (Spike) | Opus→Sonnet | Wegwerf Proof-of-Correctness vor Produktion | +| Reviewer (Gate) | **Opus, immer** | unabhängiger Review-Pass nach jedem Implement | +| Scholar / Doc | Haiku | Docs, Citations, CLI-Glue | +| Human | — | Richtung, Lizenz, Precision-Substrat, Freigabe | + +Vollständige Matrix + Entscheidungsregel: `docs/roles/model-routing.md`. + +## Zwei Loops (komposit) + +- **Feature-Loop (vorwärts):** Roadmap → Port/Research-Klassifikation → + [Research: Theorist → Spike → GO/NO-GO] → Worker parallel → Review-Gate (Opus) → + Integration → Tests + Doku + Manifest → Quality-Gate. +- **Audit-Loop (rückwärts):** kalter Auditor (Opus) → Findings mit Model-Zuweisung → + Implement-Sessions → Review-Gate (Opus, kalt) → Korrektur-Tasks → Observability-Gate. + +Die Loops komplementieren sich: Feature-Dev produziert, Audit härtet ab. +Jedes Merge triggert einen Audit-Backlog-Eintrag (expliziter Handoff). + +## Drei Schlüsselprinzipien + +1. **Review-Gate nach jeder Implement-Session** — immer Opus, immer kalt (eigene + Session). Implement-Modell ≠ Review-Modell ist eine Korrektheitseigenschaft. +2. **Spike vor Research-Code** — throwaway Proof-of-Correctness auf einem Wegwerf-Branch. + NO-GO ist ein valides Ergebnis, kein Versagen. Schützt vor wochen-langen falschen Implementierungen. +3. **Session-Prompts kaltstartfähig** — jede Session hat einen vollständigen Prompt + unter `session-prompts/` (Modell, Branch, Scope, Befehle, Akzeptanzkriterien). + +## Clean-Start-Invariante +Am Ende **jeder** Session muss gelten: ein neuer Agent kann sich allein über +`AGENTS.md → STATE.md → CONVENTIONS.md` orientieren. Das erzwingt das +Session-Hygiene-Gate. + +## Loslegen (neues Projekt) +1. `bash scripts/init.sh "Projektname"` — macht den Klon zu deinem Projekt + (Template-Overview wandert nach `docs/about-template.md`). +2. `session-prompts/BOOTSTRAP.md` in eine frische Leader-Session geben, Projekt-Brief + anhängen → der Leader füllt Board (`ROADMAP.md`), `STATE.md`, `CONVENTIONS.md` + und erzeugt die ersten Session-Prompts. +3. Die Gates sind **dormant**, bis die erste Session `STATE.md` befüllt — danach greifen sie automatisch. + +> **Erst verstehen?** `examples/walkthrough/` zeigt ein komplett befülltes Beispiel +> (Board, Session-Log, Audit-Finding, ADR) an einer generischen Domäne. + +## Einstieg (jede Session) +Jeder Agent liest zuerst **`AGENTS.md`**. Methodik im Detail: `docs/methodology.md`. diff --git a/docs/adr/0001-record-architecture-decisions.md b/docs/adr/0001-record-architecture-decisions.md new file mode 100644 index 0000000..c2169f6 --- /dev/null +++ b/docs/adr/0001-record-architecture-decisions.md @@ -0,0 +1,9 @@ +# 0001 — Entscheidungen als ADR festhalten + +- **Status:** accepted +- **Kontext:** Agenten-Sessions sind flüchtig; ohne festgehaltenes *Warum* + entstehen Drift und Wiederholungsfehler. +- **Entscheidung:** Tragende Entscheidungen werden als ADR unter `docs/adr/` + dokumentiert und in `CONVENTIONS.md` als verbindlich referenziert. +- **Konsequenz:** Minimaler Schreibaufwand pro Entscheidung; dafür kalt lesbare + Begründungen und weniger Re-Litigation. diff --git a/docs/adr/0002-ollama-native.md b/docs/adr/0002-ollama-native.md new file mode 100644 index 0000000..4f811e5 --- /dev/null +++ b/docs/adr/0002-ollama-native.md @@ -0,0 +1,18 @@ +# 0002 — Ollama-natives Modell-Management, kein eigener Swapper/Gateway + +- **Status:** accepted +- **Kontext:** Jetson Orin Nano Super 8 GB (~7,4 GB nutzbar), Single-User, + latenzgebunden. Drei Profile (light/gemma/heavy) nötig, aber nie zwei gleichzeitig + resident. Frühere Ansätze hätten einen eigenen Modell-Swapper oder ein API-Gateway + vor Ollama gesetzt. +- **Entscheidung:** Der **Ollama-Daemon serviert die Modelle nativ** (Wechsel per + Modellname über die OpenAI-kompatible API). `OLLAMA_MAX_LOADED_MODELS=1` hält genau + ein Modell resident (8-GB-Schutz); ein weiteres Profil belegt erst bei Anfrage + Speicher. **Kein eigener Swapper, kein Gateway.** **DVC bleibt Modell-Source-of- + Truth**, Ollamas Blob-Store ist nur Laufzeit-Cache. +- **Konsequenz:** Drei Profile quasi gratis (laden on-demand), kein Custom-Code für + Modellwechsel, kleinere Angriffsfläche. Preis: kurzer `OLLAMA_KEEP_ALIVE=30s` → + Ladezeit beim Profilwechsel — bei Single-User akzeptabel (keine fremde Session wird + unterbrochen). Externer Zugriff/Auth/Metrik-Aggregation liegen bewusst off-box + (nginx-Proxy, Prometheus) — siehe `CONVENTIONS.md` Scope-Grenze. +- **Superseded by:** _(noch keins)_ diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..9bf11fa --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,5 @@ +# Architecture Decision Records (ADR) + +Jede tragende Entscheidung wird als kurzes, nummeriertes ADR festgehalten — +so weiß jede künftige Session das *Warum*. Format: `NNNN-kurz-titel.md`. +Status: proposed / accepted / superseded. Neues ADR statt altes umschreiben. diff --git a/docs/gates/observability-gates.md b/docs/gates/observability-gates.md new file mode 100644 index 0000000..b33ee71 --- /dev/null +++ b/docs/gates/observability-gates.md @@ -0,0 +1,20 @@ +# Observability-Gates + +Überwachen das **System**, nicht ein einzelnes Feature. Speisen den Audit-Loop. + +## 1. System-Effizienz (Metriken über Zeit) +- Features pro Session · **Rework-Rate** (Commits, die frühere Arbeit korrigieren) +- Test-Pass-Rate · **Tokens pro Feature** · Zykluszeit · Gate-Fehlerquote +- Quelle: Session-Logs + Git-Log, aggregiert von `scripts/metrics.sh` nach + `metrics/`. + +## 2. Doku-Drift (automatisch erkennbar) +- Jeder Manifest-Eintrag: referenzierte Datei existiert **und** Test grün? +- `STATE.md` "Now" nicht älter als N Sessions (Stale-Signal). +- Code ohne Doc-Änderung / Doc ohne Code-Änderung -> Drift-Verdacht (Heuristik + aus `git diff --name-only`). +- Tote Links / referenzierte, aber fehlende ADRs. +- Quelle: `scripts/gate-doc-drift.sh`. Befund -> sofortiger Audit-Trigger. + +## Schwellen (anpassbar) +Rework-Rate > 20 %, Stale-State > 3 Sessions oder Drift-Treffer > 0 ⇒ Audit-Loop. diff --git a/docs/gates/quality-gates.md b/docs/gates/quality-gates.md new file mode 100644 index 0000000..624fdba --- /dev/null +++ b/docs/gates/quality-gates.md @@ -0,0 +1,26 @@ +# Quality-Gates + +Laufen am Session-Ende und in CI. Jedes Gate: **PASS/FAIL** + Checkliste. +`FAIL` blockt den Merge bzw. erzeugt einen Korrektur-Task. + +## 1. Session-Hygiene +- [ ] `STATE.md` in dieser Session aktualisiert. +- [ ] Session-Log unter `sessions/` angelegt (mit Token-Verbrauch). +- [ ] Working Tree sauber, Commits konventionskonform. +- [ ] **Clean-Start-Invariante** erfüllt (Orientierung allein aus + AGENTS/STATE/CONVENTIONS). +- Automatisierung: `scripts/gate-session-hygiene.sh`. + +## 2. Kontext-Pflege +- [ ] Doku ist Single Source of Truth, keine Duplikate. +- [ ] Doc-Größenbudget eingehalten (Drift-Risiko bei überlangen Docs). +- [ ] Manifest deckt sich mit der Realität (Dateien/Tests existieren). +- [ ] Keine toten Verweise. + +## 3. Token-Verbrauch +- [ ] Session-Log enthält input/output/total Tokens und Tokens-pro-Task. +- [ ] Budget nicht überschritten; auffälliges Re-Reading vermerkt. +- [ ] Trend über Sessions in `metrics/` fortgeschrieben. + +→ Vollständige Tier-1/2/3-Anleitung (Session-Schnitt, Command-Disziplin, + Cache-Disziplin): **`docs/token-hygiene.md`** (Single Source of Truth). diff --git a/docs/loops/audit-loop.md b/docs/loops/audit-loop.md new file mode 100644 index 0000000..81a2c64 --- /dev/null +++ b/docs/loops/audit-loop.md @@ -0,0 +1,54 @@ +# Audit-Loop (rückwärts) + +Ziel: Korrektheit & Hygiene erhalten, Drift früh fangen. + +``` +Kalter Auditor (Opus, neue Session) + -> Orientierung allein aus AGENTS/STATE/CONVENTIONS pruefen + -> Manifest verifizieren + Tests ausfuehren + -> Drift & Hygiene-Befunde sammeln + -> audits/.md: Finding-Tabelle mit Severity + Model-Zuweisung + -> Korrektur-Tasks in ROADMAP/STATE einstellen + -> Observability-Gate (Effizienz + Doku-Drift) aktualisieren +``` + +## Trigger +Nach N Feature-Zyklen, oder sofort bei Drift-Signal aus den Observability-Gates. + +## Finding-Orchestration + +Findings werden in `audits/.md` **mit Model-Zuweisung** erfasst: + +| ID | Typ | Sev | Status | Model | Session | +|----|-----|-----|--------|-------|---------| +| F-01 | drift | 🔴 | ⬜ | Sonnet | S1 | +| F-02 | hygiene | 🟡 | ✅ abc123 | Haiku | S1 | + +Severity: 🔴 hoch · 🟡 mittel · 🔵 niedrig + +Model-Routing (s. `docs/roles/model-routing.md`): +- **Haiku** — mechanisch, lokal, kein Risiko (Docs, Umbenennen, Konstanten) +- **Sonnet** — klare Akzeptanzkriterien (Tests, Error-Handling, kleine API-Änderungen) +- **Opus** — Numerik, Architektur, irreversible Entscheidungen + **jede Review-Gate-Session** + +Entscheidungs-Regel: nicht "wie schwer", sondern "wie viel muss **verstanden** werden, +um es richtig zu machen." + +## Session-Sequenz + +Findings werden in Sessions gebündelt (ähnliche Model-Zuweisung, ähnlicher Scope). +Nach jeder Implement-Session kommt eine **Opus-Review-Session** (kalt, unabhängig): + +``` +Implement-Session (Sonnet/Haiku) + -> dedizierten Review-Gate-Session (Opus, kalt) + APPROVE → Finding ✅ + Commit-Ref eintragen + CHANGES-REQUESTED → zurück zu Implement +``` + +Kaltstartfähige Prompts für jede Session: `session-prompts/`. + +## Ergebnis +Priorisierte Korrektur-Tasks mit Model-Zuweisung, die der nächste Feature-Loop +abräumt. Handoff zu Feature-Dev: jedes bereinigte Finding bestätigt, dass das +Repo wieder der Clean-Start-Invariante genügt. diff --git a/docs/loops/feature-loop.md b/docs/loops/feature-loop.md new file mode 100644 index 0000000..49695b2 --- /dev/null +++ b/docs/loops/feature-loop.md @@ -0,0 +1,62 @@ +# Feature-Loop (vorwärts) + +Ziel: neue Fähigkeit, sauber dokumentiert und belegt. + +## Kern-Pipeline + +``` +Roadmap-Item + -> Leader klassifiziert (port / research / infra) + -> Leader zerlegt in disjunkte Pakete (+ STATE-Ownership) + + ┌── PORT ────────────────────────────────────────────┐ + │ Worker (Sonnet): golden-oracle Implementierung │ + │ Validation (Sonnet): Parität-Tests │ + └────────────────────────────────────────────────────┘ + + ┌── RESEARCH ─────────────────────────────────────────────────────────┐ + │ Theorist (Opus): Formeln aus Papers ableiten, Validation entwerfen │ + │ Spike (Prototyper): Wegwerf-Implementierung auf scratch/**-Branch │ + │ GO/NO-GO-Gate: math korrekt? → GO: weiter; NO-GO: → Roadmap │ + │ Research-Implementer (Opus→Sonnet): produktiv umsetzen │ + └─────────────────────────────────────────────────────────────────────┘ + + -> Validation Engineer: Test-Batterie je Item-Typ bauen + -> Review-Gate (Opus, kalt): math korrekt? Parität? Public-API ok? + APPROVE → weiter | CHANGES-REQUESTED → zurück zu Implement + -> Leader integriert & löst Konflikte + -> Manifest + Docs + STATE aktualisiert + -> Quality-Gate (Hygiene/Kontext/Token) + PASS: Item nach "Done" | FAIL: Korrektur-Task +``` + +## Klassifikation Port vs. Research + +| Typ | Kriterium | Oracle | Validation-Pflicht | +|---|---|---|---| +| **Port** | hat Referenz-Implementierung (Java, Python, Pseudo-Code) | golden values bit-for-bit | FD-Gradient + Parität | +| **Research** | kein direkter Vorläufer, nur Paper-Formeln | keine extern | Invarianten + analyt. Grenzfälle + Konvergenz | +| **Infra** | kein fachlicher Inhalt (CLI, CI, Docs) | trivial | Smoke-Test | + +Regel: Research-Items **müssen** durch das Spike-Gate, bevor Produktions-Code +geschrieben wird. Näheres: `docs/loops/spike-gate.md`. + +## Model-Routing (grobe Heuristik) + +Vollständige Matrix: `docs/roles/model-routing.md`. Kurzform: +- Mechanische Arbeit (Umbenennen, Docs, CLI-Glue) → **Haiku** +- Implementierung mit klarer Spec → **Sonnet** +- Mathe, Architektur, jede Review-Gate-Session → **Opus** + +## Session-Prompts + +Kaltstartfähige Prompts je Phase/Paket unter `session-prompts/`. +Template: `session-prompts/TEMPLATE.md`. + +## Eintrittskriterien +Roadmap-Item priorisiert; Klassifikation (Port/Research/Infra) klar; +betroffene Konventionen geklärt. + +## Austrittskriterien (Definition of Done, s. CONVENTIONS.md) +Tests grün · Manifest `done` · Docs/STATE aktuell · Session-Log · +Review-Gate `APPROVE` · Hygiene-Gate `PASS`. diff --git a/docs/loops/spike-gate.md b/docs/loops/spike-gate.md new file mode 100644 index 0000000..cf62db9 --- /dev/null +++ b/docs/loops/spike-gate.md @@ -0,0 +1,55 @@ +# Spike-Gate (nur Research-Items) + +Bevor Research-Mathe produktivsiert wird: numerischer Proof-of-Correctness +auf einem **Wegwerf-Branch**. Der Spike schützt davor, Wochen in eine +mathematisch falsche Implementierung zu investieren. + +## Warum + +Research-Items haben keinen goldenen Oracle (keine Referenz-Implementierung). +Eine Implementierung kann kompilieren, konvergieren und trotzdem **geometrisch +falsch** sein. Invarianten-Checks und Konvergenz-Studien fangen das nur, wenn +die zu prüfenden Invarianten vorab klar spezifiziert wurden. + +## Ablauf + +``` +Theorist (Opus): + Formeln aus Papers/Dissertation ableiten + Validation-Strategie entwerfen (Invarianten, analyt. Grenzfälle, Kreuzcheck) + LaTeX-Notiz / Spec-Dokument erstellen + ↓ +Prototyper (Opus → Sonnet): + Throwaway-Implementierung auf Branch `spike/` + Numerischen Korrektheitsnachweis führen (die vom Theorist entworfene Validation) + ↓ +GO/NO-GO-Gate: + GO → Spike-Branch wird verworfen; Research-Implementer baut produktiv + NO-GO → Spike-Branch bleibt als Dokumentation des negativen Ergebnisses + → Eintrag in ROADMAP: "Spike FAILED — Grund: …" + → Zurück zum Theorist oder Human-Entscheidung +``` + +## NO-GO ist kein Versagen + +Ein NO-GO ist ein valides, wertvolles Ergebnis. Es dokumentiert, dass ein +Ansatz numerisch nicht funktioniert, bevor Produktionscode und Tests dafür +investiert wurden. **Negative Spikes müssen genauso sorgfältig dokumentiert +werden wie erfolgreiche.** + +## Validation-Typen (gewählt vom Theorist) + +| Situation | Validation | +|---|---| +| Cross-Implementierung verfügbar (andere Bibliothek) | Übereinstimmung nach Normalisierung | +| Analytische Grenzfälle bekannt (z. B. κ=0 ↔ Euklidisch) | Bit-for-bit-Übereinstimmung am Grenzfall | +| Erhaltungsgrößen bekannt (Gauss-Bonnet, Holonomie-Closure) | Invarianten-Check unter Perturbation | +| Analytisch vs. numerisch (FD vs. exakte Hessematrix) | Wert-Identität + Speed-Messung | +| Kein direkter Check möglich | Konvergenz-unter-Verfeinerung-Studie | + +## Aufwand-Faustregel + +Ein Spike sollte **höchstens 20 % des Aufwands** einer vollständigen +Implementierung kosten. Wenn er mehr braucht, ist das Scope entweder falsch +klassifiziert (→ kleineres Research-Item) oder der Theorist hat die Spec +nicht ausreichend präzisiert (→ zurück zum Theorist). diff --git a/docs/methodology.md b/docs/methodology.md new file mode 100644 index 0000000..d0a57c2 --- /dev/null +++ b/docs/methodology.md @@ -0,0 +1,48 @@ +# Methodik — Betriebsmodell + +## Grundprinzip +Das Repo ist die dauerhafte Erinnerung; Sessions sind flüchtig. Alles +Entscheidungsrelevante liegt **auf Disk**, nie nur im Chat. So kann jede neue +Session kalt starten. + +## Rollen +- **Leader** (`docs/roles/leader.md`) — Orchestrierung & Integration. +- **Worker** (`docs/roles/worker.md`) — disjunkte parallele Umsetzung. +- **Reviewer** (`docs/roles/reviewer.md`) — kalter Audit in neuer Session; immer Opus. +- **Model-Routing** (`docs/roles/model-routing.md`) — welches Modell für welche Arbeit. + +## Zwei Loops (Feature-Dev und Audit) + +- **Feature-Loop / vorwärts** (`docs/loops/feature-loop.md`): erzeugt Fähigkeit. + Enthält eine **Port/Research-Klassifikation** und (für Research) ein + **Spike-Gate** (`docs/loops/spike-gate.md`) bevor Produktionscode entsteht. +- **Audit-Loop / rückwärts** (`docs/loops/audit-loop.md`): erhält Korrektheit & + Hygiene, speist Korrekturen mit Model-Zuweisung zurück in Roadmap/State. + +Die Loops **komplementieren sich**: Feature-Dev produziert Module; Audit härtet +sie ab. Jedes Merge im Feature-Loop triggert einen Audit-Backlog-Eintrag. +Die Loops wechseln sich ab: nach N Feature-Zyklen ein Audit-Zyklus (oder sofort +bei Drift-Signal aus den Observability-Gates). + +## Review-Gate (eingebaut in beide Loops) + +Nach **jeder** Implement-Session kommt eine separate Opus-Session (kalt, +unabhängig), die den Diff reviewt. Kein Merge ohne Review-Gate `APPROVE`. +Details: `docs/roles/reviewer.md`. + +## Session-Prompts + +Für jede Session existiert ein kaltstartfähiger Prompt unter `session-prompts/`. +Template: `session-prompts/TEMPLATE.md`. Der Prompt enthält: Modell, Branch, +Scope, Befehle, Akzeptanzkriterien — alles was die Session ohne Vorkontext braucht. + +## Gates +- **Quality-Gates** (`docs/gates/quality-gates.md`): Session-Hygiene, + Kontext-Pflege, Token-Verbrauch. +- **Observability-Gates** (`docs/gates/observability-gates.md`): System-Effizienz + und Doku-Drift. +- **Token-Hygiene** (`docs/token-hygiene.md`): 3-Tier-System zur Kostensteuerung. + +## Clean-Start-Invariante +Session-Ende ⇒ neuer Agent orientiert sich allein über +`AGENTS.md → STATE.md → CONVENTIONS.md`. Verletzung = Hygiene-Gate `FAIL`. diff --git a/docs/roles/leader.md b/docs/roles/leader.md new file mode 100644 index 0000000..4d4a7ba --- /dev/null +++ b/docs/roles/leader.md @@ -0,0 +1,17 @@ +# Rolle: Leader + +## Auftrag +Arbeit zerlegen, zuweisen, integrieren — nicht selbst alle Pakete bauen. + +## Ablauf (Feature-Loop) +1. Oberstes Roadmap-Item ziehen, in **disjunkte Worker-Pakete** zerlegen + (klare Datei-Ownership, minimale Kopplung). +2. Ownership-Tabelle in `STATE.md` eintragen; offene Fragen vorab in + `CONVENTIONS.md`/ADR klären, damit Worker nicht divergieren. +3. Worker parallel dispatchen. Während sie laufen: nichts in ihren Dateien ändern. +4. **Integrieren:** zusammenführen, Konflikte lösen, Schnittstellen prüfen. +5. Manifest + Docs + `STATE.md` aktualisieren, Quality-Gate ausführen. + +## Regeln +- Konflikte gehören dir, nicht den Workern. +- Wenn ein Paket > 1 Worker-Session braucht: weiter zerlegen. diff --git a/docs/roles/model-routing.md b/docs/roles/model-routing.md new file mode 100644 index 0000000..eef5ddc --- /dev/null +++ b/docs/roles/model-routing.md @@ -0,0 +1,58 @@ +# Model-Routing — Zuweisung nach Aufgabentyp + +Vollständige Entscheidungsmatrix. Kurzform in `docs/loops/feature-loop.md`. + +> **Tier-Sprache statt feste Modellnamen:** Modellnamen veralten; die Tier-Logik +> (klein/mittel/hoch) bleibt. Konkrete Modell-IDs (z. B. Haiku 4.5, Sonnet 4.6, +> Opus 4.8) sind aktuelle Beispiele — beim Provider nachschlagen, wenn neue +> Versionen verfügbar sind. + +## Tiers + +| Tier | Eigenschaft | Aktuelle Beispiele (Anthropic Claude) | +|------|-------------|---------------------------------------| +| **klein** | schnell, günstig, ausreichend für klar spezifizierte, mechanische Arbeit | Haiku | +| **mittel** | ausgewogen; guter Coder bei klarer Spec | Sonnet | +| **hoch** | höchste Reasoning-Kapazität; für Unklarheiten, Mathe, Review | Opus | + +## Routing-Matrix + +| Aufgabe | Rolle · Tier | +|---|---| +| Mechanisch, lokal, kein Risiko: Docs, Umbenennen, Konstanten, CLI-Glue | klein | +| Faithful Translation von bekannter Referenz (Port, golden oracle) | Porter · mittel | +| Implementierung mit klarer Spec + Akzeptanzkriterien: Tests, Error-Handling | mittel | +| Numerik, Architektur, Mathe von Grund auf, irreversible Public-API-Entscheidungen | hoch | +| Formeln aus Papers ableiten, Validation-Strategie entwerfen | Theorist · hoch | +| Throwaway Proof-of-Correctness (Spike), bevor Produktionscode entsteht | Prototyper · hoch → mittel | +| Test-Batterie für abgeschlossene Implementierung | Validation · mittel | +| **Jede Review-Gate-Session** (unabhängig, kalt) | **Reviewer · hoch** | +| Docs polieren, Referenz-Listen, Tutorials | Scholar · klein | +| Branch/PR/CI/Rebase/Merge | Integrator · mittel | +| Fachliche Richtungsentscheidungen, Lizenz, Precision-Substrat | Human | + +## Entscheidungsregel + +**Nicht** „wie schwer ist das Finding/Feature", sondern: +**„Wie viel muss *verstanden* werden, um es richtig zu machen?"** + +- Eine 1-Zeilen-Korrektur mit klarer Spec → mittel (auch wenn 🔴 Severity). +- Eine numerische Umformulierung mit Auswirkung auf Korrektheit → hoch + (auch wenn 🔵 Severity). + +## Review-Gate-Regel + +Die Review-Gate-Session ist **immer höchste Kapazitätsstufe und immer kalt** +(eigene Session, kein Vorkontext aus der Implement-Session). Implement-Tier ≠ +Review-Tier ist keine Effizienzfrage, sondern eine Korrektheitseigenschaft. + +## Routing Port vs. Research + +``` +Gibt es eine Referenz-Implementierung / goldene Werte? + JA → Port → Porter (Sonnet), golden-oracle parity-Tests Pflicht + NEIN → Research → Theorist (Opus) ableiten → Spike → GO/NO-GO + → Research-Implementer (Opus→Sonnet) produktivisieren +``` + +Details zum Spike-Gate: `docs/loops/spike-gate.md`. diff --git a/docs/roles/reviewer.md b/docs/roles/reviewer.md new file mode 100644 index 0000000..2092dd8 --- /dev/null +++ b/docs/roles/reviewer.md @@ -0,0 +1,41 @@ +# Rolle: Externer Reviewer (kalt) + +## Auftrag +In einer **frischen Session ohne Vorkontext** verifizieren, ob das Repo stimmt +und ob ein Neuling sich orientieren kann. + +**Modell: immer Opus.** Rationale: ein unabhängiger, kapazitätsstarker Pass +nach jedem Implement findet systematisch andere Fehler als das implementierende +Modell. Der Reviewer darf niemals dasselbe Modell in derselben Session gewesen sein. + +## Zwei Reviewer-Rollen + +### 1. Review-Gate (nach jeder Implement-Session, Feature- wie Audit-Loop) +Geht den Diff durch — nicht das ganze Repo. Prüft: + +- [ ] Build sauber; Test-Suite grün (keine Regressions im Zählstand). +- [ ] Keine golden-vector / Parität-Tests verändert, sofern nicht explizit begründet. +- [ ] Numerische Änderungen sind wert-identisch wo behauptet, oder getestet. +- [ ] Neue Public-Surface (Typen, Enums, API) ist absichtlich und dokumentiert. +- [ ] Commit-Message enthält Model-Attribution des Implementers. +- [ ] Finding / Phase als ✅ in der Orchestration-Tabelle mit Commit-Ref eingetragen. + +Ergebnis: **APPROVE** oder **CHANGES-REQUESTED** (mit konkreter Liste). + +### 2. Audit-Reviewer (periodisch, Audit-Loop) +Startet komplett kalt — kein Vorkontext aus vorherigen Sessions. + +1. **Nur** `AGENTS.md → STATE.md → CONVENTIONS.md` lesen. Orientierung gelungen? + (Ja/Nein → erstes Finding.) +2. `manifests/requirements.md` durchgehen: Dateien vorhanden? Tests lauffähig? +3. **Drift suchen:** Docs vs. Code, ADRs vs. Realität, `STATE.md`-Aktualität, + tote Verweise, ungetestete Behauptungen. +4. **Hygiene prüfen:** Ownership-Verstöße, Doppel-Dokumentation, Doc-Budget. +5. Findings nach `audits/.md` (Template) mit Severity + Model-Zuweisung. + Korrektur-Tasks in `ROADMAP.md` / `STATE.md` einstellen. + Observability-Gate aktualisieren. + +## Prinzip +Der Reviewer baut keine Features — er deckt Lücken zwischen *behauptet* und +*belegt* auf. Er nimmt an, dass alle Aussagen im Repo falsch sind, bis er sie +selbst verifiziert hat. diff --git a/docs/roles/worker.md b/docs/roles/worker.md new file mode 100644 index 0000000..75acc14 --- /dev/null +++ b/docs/roles/worker.md @@ -0,0 +1,14 @@ +# Rolle: Worker + +## Auftrag +Genau **ein** zugewiesenes Paket umsetzen — innerhalb der eigenen Dateigrenzen. + +## Ablauf +1. `AGENTS.md`-Reihenfolge lesen, dann nur die für dein Paket relevanten Dateien. +2. Gegen den Vertrag in `CONVENTIONS.md` bauen (Naming/Pfade/Schnittstellen). +3. Tests für dein Paket schreiben; Manifest-Einträge auf `in_progress`/`done` setzen. +4. **Niemals** Dateien außerhalb deines Pakets anfassen — sonst Notiz an den Leader. +5. Session-Log schreiben (inkl. Token-Verbrauch), Hygiene-Gate ausführen. + +## Anti-Pattern +- Scope-Creep, "mal eben" fremde Dateien anpassen, Doku "später". diff --git a/docs/token-hygiene.md b/docs/token-hygiene.md new file mode 100644 index 0000000..22864ac --- /dev/null +++ b/docs/token-hygiene.md @@ -0,0 +1,50 @@ +# Token-Hygiene — 3 Ebenen + +Jeder Turn schickt die ganze Konversations-History erneut. Kontextakkumulation +ist der größte vermeidbare Kostenfaktor in Multi-Agenten-Setups. + +--- + +## Tier 1 — Session-Schnitt (höchste Wirkung) + +- **Eine Session pro Aufgabe.** Nach einer abgeschlossenen Aufgabe `/clear` starten + statt zum nächsten Thema im selben Thread zu wechseln. Alter Kontext ist totes + Gewicht in jedem weiteren Turn. +- **Proaktiv kompaktieren** an sauberen Übergabepunkten. `/compact ` + bevor die nächste Aufgabe startet — nicht warten bis auto-compaction einsetzt + (Zeitpunkt ist nicht kontrollierbar). +- **Lese-intensive Sweeps delegieren.** Ein Explore/Plan-Subagent liest in seinem + eigenen Kontext und gibt eine kurze Zusammenfassung zurück — das Bulk landet nie + im Hauptkontext. Nur bei bekannten Pfaden direkt `Read` nutzen. + +## Tier 2 — Command-Disziplin (mittlere Wirkung) + +- **Scope + Filter gemeinsam.** Pfad-scopede Suchen (`grep -rn "symbol" src/`, nicht + Repo-weit). Test-Output filtern (`--filter "SuiteX"`, nicht alle Ergebnisse dumpen). +- **Logs nie roh in Kontext.** In Datei umleiten, dann `grep`/`tail`. Bei + Hintergrund-Jobs Output-Datei selektiv lesen, nicht pauschal. +- **Nicht zurück-lesen nach Edit.** `Edit` schlägt fehl bei inkonsistentem State — + ein erfolgreicher Edit braucht kein `Read` zur Verifikation. +- **Referenz per Zeilennummer** (`datei.py:147`) statt Code-Blöcke neu einzufügen. + +## Tier 3 — Cache-Disziplin (Prompt-Cache, TTL 5 min) + +Der stabile Präfix jeder Anfrage (System-Prompt + CLAUDE.md / AGENTS.md) wird +gecacht. Cache-Miss = der ganze Kontext wird uncached neu gelesen. + +- **Stabilen Präfix stabil halten.** `AGENTS.md`, `CLAUDE.md` und Projekt-Config + **nicht mitten in einer Arbeitssession editieren**. Änderungen sammeln und in + einem eigenen Durchgang machen. +- **Keine Ketten kurzer Pausen.** Einzelne lange Pause (> 5 min) = ein Cache-Miss. + Viele kurze „warte-mal-kurz"-Turns mit Lücken > 5 min = jedes Mal ein neuer Miss. + Bei externem Warten (CI, Deploy): **einmal** lang warten statt mehrfach pollen. +- **Eine Session pro Thema** (interagiert direkt mit Cache): frischer Thread = kleiner, + vollständig gecachter Präfix. + +--- + +## Schnell-Check vor einer langen Session + +- [ ] Einzelnes Thema? Wenn nein → splitten. +- [ ] AGENTS.md-Änderungen anstehend? → **vorher** erledigen, dann stabil lassen. +- [ ] Lange Wartezeiten erwartet (CI/Build)? → Hintergrund-Job + **einmal** warten. diff --git a/manifests/requirements.md b/manifests/requirements.md new file mode 100644 index 0000000..9708cbe --- /dev/null +++ b/manifests/requirements.md @@ -0,0 +1,20 @@ +# Requirements-Manifest (kalt verifizierbar) + +Eine Zeile je Erfolgskriterium — der **kalt lesbare Review** (siehe `REVIEW.md`). +Der Reviewer prüft Spalte für Spalte; `done`-Zeilen müssen ihren Prüfbefehl bestehen. +`scripts/gate-doc-drift.sh` erzwingt die Existenz der Pfade in `done`/`in_progress`-Zeilen. + +| ID | Anforderung | Datei(en) | Test/Prüfbefehl | Status | +|----|-------------|-----------|------------------|--------| +| R-01 | Vertrag zuerst: CONVENTIONS + disjunkte Ownership | `CONVENTIONS.md`, `STATE.md` | `grep -q qwen-light CONVENTIONS.md` | done | +| R-02 | Drei Profile über Modelfiles (light/gemma/heavy) | `ollama/Modelfile.light`, `ollama/Modelfile.gemma`, `ollama/Modelfile.heavy` | `pytest tests/test_modelfiles.py` | todo | +| R-03 | q8_0-KV + Flash Attention + MAX_LOADED_MODELS=1 | `ollama/systemd/ollama.service.d/override.conf` | `grep -Eq 'q8_0' ollama/systemd/ollama.service.d/override.conf` | todo | +| R-04 | num_ctx je Profil explizit (light/gemma 16384, heavy 8192) | `ollama/Modelfile.light`, `ollama/Modelfile.heavy` | `grep -q 'num_ctx' ollama/Modelfile.light` | todo | +| R-05 | GPU-Nutzung verifiziert; Ollama nur LAN + Firewall | `scripts/setup-jetson.sh` | `bash -n scripts/setup-jetson.sh` | todo | +| R-06 | Metrik-Endpoint über Exporter (`:8000/metrics`) | `exporter/systemd/ollama-exporter.service` | `pytest tests/test_endpoints.py` | todo | +| R-07 | Keine Secrets; `.env.example` nur Platzhalter | `.env.example` | `grep -q 'JETSON_LAN_IP=' .env.example` | todo | +| R-08 | DVC = Modell-Source-of-Truth; build reproduzierbar | `scripts/build-models.sh`, `.dvc/config` | `bash -n scripts/build-models.sh` | todo | +| R-09 | Client + CLI funktionsfähig (OpenAI-kompatibel) | `client/python/jetson_ai/client.py`, `client/cli/ai.py` | `pytest tests/` | todo | +| R-10 | Kalt verifizierbar; Tests kodieren Kriterien | `REVIEW.md`, `tests/test_endpoints.py` | `pytest tests/ -q` | todo | + +Status: `todo` · `in_progress` · `done` · `drift` (vom Audit markiert). diff --git a/metrics/efficiency.csv b/metrics/efficiency.csv new file mode 100644 index 0000000..78a0651 --- /dev/null +++ b/metrics/efficiency.csv @@ -0,0 +1,2 @@ +date,sessions,rework_commits,total_commits +2026-06-03,0,0,0 diff --git a/scripts/gate-doc-drift.sh b/scripts/gate-doc-drift.sh new file mode 100755 index 0000000..dde7a25 --- /dev/null +++ b/scripts/gate-doc-drift.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# Doku-Drift-Gate: prueft Manifest-Referenzen + STATE-Aktualitaet + Doc-Budget. +set -uo pipefail +fail=0; man="manifests/requirements.md" + +# Dormant solange das Template nicht initialisiert ist (scripts/init.sh). +if grep -q '' STATE.md 2>/dev/null; then + echo "[drift] Template noch nicht initialisiert (scripts/init.sh) — uebersprungen." + echo "GATE: PASS"; exit 0 +fi + +echo "[drift] pruefe im Manifest referenzierte Pfade (nur done/in_progress/drift)..." +# Nur Pfade aus ERLEDIGTEN Zeilen muessen existieren — 'todo'-Zeilen sind Plan, +# ihre Dateien gibt es absichtlich noch nicht. Treffer in eine Datei sammeln, +# damit fail=1 nicht in einer Pipe-Subshell verloren geht. +miss=$(mktemp) +if [ -f "$man" ]; then + while IFS= read -r line; do + case "$line" in \|*) : ;; *) continue ;; esac # nur Tabellenzeilen + status=$(printf '%s' "$line" | sed 's/^|//; s/|[[:space:]]*$//' \ + | awk -F'|' '{print $NF}' | tr -d ' ' | tr 'A-Z' 'a-z') + case "$status" in done|in_progress|drift) : ;; *) continue ;; esac + while IFS= read -r tok; do + case "$tok" in *" "*|*…*|_*|*path/to*) continue ;; esac + case "$tok" in + */*|*.py|*.md|*.sh|*.js|*.ts|*.yml|*.yaml|*.json|*.conf|*.ini|*.txt) + [ -e "$tok" ] || echo "$status $tok" >> "$miss" ;; + esac + done < <(printf '%s\n' "$line" | grep -oE '`[^`]+`' | tr -d '`') + done < "$man" +fi +if [ -s "$miss" ]; then + while IFS=" " read -r st p; do echo " - fehlende Referenz (Status $st): $p"; done < "$miss" + fail=1 +fi +rm -f "$miss" + +echo "[drift] STATE.md Stale-Check (Commits seit letzter Aenderung)..." +last_state=$(git log -1 --format=%H -- STATE.md 2>/dev/null || true) +if [ -n "$last_state" ]; then + since=$(git rev-list --count "${last_state}..HEAD" 2>/dev/null || echo 0) + [ "${since:-0}" -le 3 ] || { echo " - STATE.md seit $since Commits unveraendert"; fail=1; } +fi + +echo "[drift] Doc-Groessenbudget (Faustregel < 200 Zeilen)..." +while read -r f; do + case "$f" in examples/*) continue ;; esac # Beispiele duerfen laenger sein + n=$(wc -l < "$f" 2>/dev/null || echo 0) + [ "$n" -le 200 ] || echo " - Hinweis: $f hat $n Zeilen (> 200, Drift-Risiko)." +done < <(git ls-files 2>/dev/null | grep '\.md$' || true) + +echo "[drift] Code ohne Doc-Aenderung im letzten Commit?" +files=$(git show --name-only --pretty= HEAD 2>/dev/null || true) +if echo "$files" | grep -qE '\.(py|sh|js|ts)$' && ! echo "$files" | grep -qE '\.md$'; then + echo " - Hinweis: Code geaendert, keine Doku angepasst (Drift-Verdacht)." +fi + +[ "$fail" -eq 0 ] && echo "GATE: PASS" || { echo "GATE: FAIL"; exit 1; } diff --git a/scripts/gate-ownership.sh b/scripts/gate-ownership.sh new file mode 100755 index 0000000..e9c68da --- /dev/null +++ b/scripts/gate-ownership.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# Ownership-Gate: kein Paket editiert Dateien eines anderen. +# Liest die Ownership-Tabelle aus STATE.md, mappt geaenderte Dateien (Branch vs. +# Basis) auf Pakete und FAILt bei Cross-Editing ueber >1 Paket-Grenze hinweg. +# Integration (Leader) ist ausgenommen: Branch main/master/integrate/*. +# Konvention: Verzeichnis-Pfade in der Tabelle mit Slash beenden (src/api/). +# Portabel gehalten (kein mapfile / keine assoziativen Arrays, laeuft auf bash 3.2). +set -uo pipefail + +# Dormant solange das Template nicht initialisiert ist. +if grep -q '' STATE.md 2>/dev/null; then + echo "[ownership] Template noch nicht initialisiert — uebersprungen." + echo "GATE: PASS"; exit 0 +fi + +branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "") +case "$branch" in + main|master|integrate/*) + echo "[ownership] '$branch' ist Integrations-Branch — uebersprungen." + echo "GATE: PASS"; exit 0 ;; +esac + +# (pkgprefix)-Zeilen aus der STATE.md-Ownership-Tabelle ziehen. +pairs=$(awk -F'|' ' + /Datei-Ownership/{f=1; started=0; next} + f && started && $0 !~ /^\|/ {f=0} # erst NACH Tabellenbeginn abbrechen + f && /^\|/{ + started=1; + pkg=$2; paths=$3; + gsub(/^[ \t]+|[ \t]+$/,"",pkg); + if(pkg=="" || pkg=="Paket" || pkg ~ /---/ || pkg ~ /…/ || pkg ~ /^_/) next; + n=split(paths, a, ","); + for(i=1;i<=n;i++){ p=a[i]; gsub(/^[ \t]+|[ \t]+$/,"",p); gsub(/`/,"",p); + if(p=="" || p ~ /…/ || p ~ /^_/) continue; + print pkg "\t" p } + }' STATE.md 2>/dev/null) + +if [ -z "$pairs" ]; then + echo "[ownership] keine befuellte Ownership-Tabelle in STATE.md — uebersprungen." + echo "GATE: PASS"; exit 0 +fi + +base=$(git merge-base HEAD main 2>/dev/null || git rev-parse HEAD~1 2>/dev/null || true) +[ -n "$base" ] || { echo "[ownership] keine Diff-Basis — uebersprungen."; echo "GATE: PASS"; exit 0; } +changed=$(git diff --name-only "$base"...HEAD 2>/dev/null) +[ -n "$changed" ] || { echo "[ownership] keine Aenderungen — uebersprungen."; echo "GATE: PASS"; exit 0; } + +hit=""; unowned="" +while IFS= read -r f; do + [ -n "$f" ] || continue + bestpre=""; bestpkg="" + while IFS=" " read -r pkg pre; do + [ -n "$pre" ] || continue + case "$f" in + "$pre"|"$pre"*) + if [ "${#pre}" -gt "${#bestpre}" ]; then bestpre="$pre"; bestpkg="$pkg"; fi ;; + esac + done <' STATE.md 2>/dev/null; then + echo "[hygiene] Template noch nicht initialisiert (scripts/init.sh) — uebersprungen." + echo "GATE: PASS"; exit 0 +fi + +echo "[hygiene] pruefe Working Tree..." +[ -z "$(git status --porcelain)" ] || note "Working Tree nicht sauber." + +echo "[hygiene] STATE.md im aktuellen Branch aktualisiert?" +base=$(git merge-base HEAD main 2>/dev/null || true) +head=$(git rev-parse HEAD 2>/dev/null || true) +if [ -n "$base" ] && [ "$base" != "$head" ]; then + # echte Divergenz (Feature-Branch): Diff gegen Abzweigpunkt + git diff --name-only "$base"...HEAD | grep -q '^STATE.md$' || \ + note "STATE.md im aktuellen Branch nicht aktualisiert." +else + # auf main/Integration oder Root-Commit: letzten Commit pruefen + git log -1 --name-only --pretty= | grep -q '^STATE.md$' || \ + note "STATE.md im letzten Commit nicht angefasst." +fi + +echo "[hygiene] Session-Log vorhanden?" +ls sessions/[0-9]*.md >/dev/null 2>&1 || note "Kein Session-Log unter sessions/." + +echo "[hygiene] Conventional Commits?" +git log -1 --pretty=%s | grep -Eq '^(feat|fix|docs|test|refactor|chore)(\(.+\))?: ' || \ + note "Letzter Commit nicht conventional." + +echo "[hygiene] Model-Attribution im letzten Commit?" +git log -1 --pretty=%B | grep -q 'Co-Authored-By: Claude' || \ + echo " - Hinweis: letzter Commit ohne 'Co-Authored-By: Claude ' (Pflicht nur fuer Agenten-Commits)." + +if [ "$fail" -ne 0 ]; then echo "GATE: FAIL"; exit 1; fi +echo "GATE: PASS" diff --git a/scripts/init.sh b/scripts/init.sh new file mode 100755 index 0000000..3a9f14e --- /dev/null +++ b/scripts/init.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# init.sh — ein Template-Klon zu einem konkreten Projekt machen. +# Nutzung: bash scripts/init.sh "Mein Projektname" +# +# Was passiert: +# - die Template-README wandert nach docs/about-template.md (Methodik bleibt erhalten) +# - eine frische, projektbezogene README.md wird geschrieben +# - falls noch kein Git-Repo: git init +# - die Gates bleiben DORMANT, bis die erste echte Session STATE.md befuellt +# (die Zeile mit '' ersetzt) — danach greifen sie automatisch. +# +# Naechster Schritt nach init: session-prompts/BOOTSTRAP.md in eine frische +# Leader-Session geben, zusammen mit deinem Projekt-Brief. +set -euo pipefail + +name="${1:-}" +if [ -z "$name" ]; then + echo "Nutzung: bash scripts/init.sh \"Projektname\"" >&2 + exit 2 +fi + +[ -f AGENTS.md ] || { echo "Bitte aus dem Repo-Root ausfuehren (AGENTS.md nicht gefunden)." >&2; exit 1; } + +if [ -f docs/about-template.md ]; then + echo "Bereits initialisiert (docs/about-template.md existiert). Abbruch." >&2 + exit 1 +fi + +# 1) Template-README bewahren, frische Projekt-README schreiben. +git mv README.md docs/about-template.md 2>/dev/null || mv README.md docs/about-template.md +cat > README.md < Arbeitet nach dem **agent-swarm**-Betriebsmodell. Jeder Agent (Mensch wie KI) +> liest zuerst [\`AGENTS.md\`](AGENTS.md). Methodik im Detail: +> [\`docs/methodology.md\`](docs/methodology.md). Herkunft des Modells: +> [\`docs/about-template.md\`](docs/about-template.md). + +## Schnellstart +- **Stand & nächster Schritt:** [\`STATE.md\`](STATE.md) +- **Plan / Ready-Set:** [\`ROADMAP.md\`](ROADMAP.md) +- **Regeln:** [\`CONVENTIONS.md\`](CONVENTIONS.md) +- **Neues Feature anstoßen:** [\`session-prompts/BOOTSTRAP.md\`](session-prompts/BOOTSTRAP.md) +EOF + +# 2) Git initialisieren, falls noetig. +if ! git rev-parse --git-dir >/dev/null 2>&1; then + git init -q + echo "[init] leeres Git-Repo angelegt." +fi + +echo "[init] '${name}' initialisiert." +echo "[init] Template-Overview liegt jetzt unter docs/about-template.md." +echo +echo "Naechster Schritt:" +echo " 1) Projekt-Brief bereithalten (Ziel, Stack, Constraints)." +echo " 2) session-prompts/BOOTSTRAP.md in eine frische Session geben (Modell: Sonnet)." +echo " 3) Der Leader fuellt ROADMAP/STATE/CONVENTIONS und erzeugt die ersten Session-Prompts." +echo +echo "Die Gates sind dormant, bis die erste Session STATE.md befuellt." diff --git a/scripts/metrics.sh b/scripts/metrics.sh new file mode 100755 index 0000000..eb2a1ea --- /dev/null +++ b/scripts/metrics.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# Observability: aggregiert Session-Logs + Git zu metrics/efficiency.csv +set -uo pipefail +mkdir -p metrics; out="metrics/efficiency.csv" +echo "date,sessions,rework_commits,total_commits" > "$out" +total=$(git rev-list --count HEAD 2>/dev/null || echo 0) +rework=$(git log --pretty=%s | grep -Ec '^(fix|refactor)(\(.+\))?: ' || true) +sess=$(ls sessions/[0-9]*.md 2>/dev/null | wc -l | tr -d ' ') +echo "$(date +%F),$sess,$rework,$total" >> "$out" +echo "[metrics] geschrieben nach $out" +echo " Rework-Rate: $rework/$total Commits" diff --git a/session-prompts/BOOTSTRAP.md b/session-prompts/BOOTSTRAP.md new file mode 100644 index 0000000..aff75e1 --- /dev/null +++ b/session-prompts/BOOTSTRAP.md @@ -0,0 +1,61 @@ +# BOOTSTRAP — neues Projekt aufsetzen (Leader-Session) + +Kopiere den Block unten in eine **frische Session** (Modell: **Sonnet**) und hänge +deinen Projekt-Brief an. Der Leader füllt das Repo aus dem Brief — du musst keine +Datei von Hand anlegen. + +> Voraussetzung: einmalig `bash scripts/init.sh "Projektname"` gelaufen. + +--- + +``` +Du bist der LEADER eines agent-swarm-Repos. Arbeite in __. + +Lies in dieser Reihenfolge und höre auf, sobald du genug Kontext hast: +AGENTS.md → STATE.md → CONVENTIONS.md → docs/methodology.md → +docs/roles/{leader,model-routing}.md → docs/loops/feature-loop.md → +ROADMAP.md (Board-Format) → examples/walkthrough/ (ein befülltes Beispiel). + +## Mein Projekt-Brief +<<< HIER deinen Brief einfügen: Ziel, Tech-Stack, harte Constraints, + erste gewünschte Fähigkeit. 3–15 Zeilen reichen. >>> + +## Deine Aufgabe (nur Planung, noch kein Feature-Code) +1. ROADMAP.md als Board befüllen: den Brief in Items zerlegen, jedes mit + Typ (🔌 port / 🔬 research / 🧱 infra), Status, Prereqs, Rolle·Modell, Aufwand. + Den Abhängigkeits-DAG explizit machen (was blockiert was). +2. CONVENTIONS.md projektspezifisch ergänzen, falls nötig: Build-/Test-Befehl, + Branch-/Remote-Konventionen, Sprache. Bestehende Regeln NICHT verwässern. + Tragende Entscheidungen als ADR unter docs/adr/ festhalten. +3. STATE.md auf den echten Startzustand setzen: die Header-Zeile mit einer echten + Session-ID/Datum füllen (ersetzt den ''-Platzhalter — DAS aktiviert + die Gates), Now/Next füllen, die Ownership-Tabelle für die ersten Pakete anlegen + (Verzeichnis-Pfade mit Slash beenden, z. B. `src/api/`). +4. Für jedes Item aus dem aktuellen READY-SET (Status 🔲, alle Prereqs ✅) einen + kaltstartfähigen Prompt unter session-prompts/.md aus + session-prompts/TEMPLATE.md erzeugen — Modell gemäß docs/roles/model-routing.md. +5. Ein Session-Log unter sessions/-bootstrap.md aus sessions/TEMPLATE.md + schreiben. Hygiene-Gate ausführen: bash scripts/gate-session-hygiene.sh. + +## Wichtig +- Du PLANST und dispatcht — du baust die Features nicht selbst. +- Research-Items (🔬) müssen vor Produktionscode durch das Spike-Gate + (docs/loops/spike-gate.md). Markiere sie entsprechend im Board. +- Halte die Single-Source-of-Truth-Regel: keine Information doppelt ablegen. +- Conventional Commit + Trailer + `Co-Authored-By: Claude Sonnet 4.6 `. + +Am Ende: zeig mir das befüllte Board (ROADMAP.md) und das Ready-Set, und sag mir, +welche Session-Prompts du erzeugt hast und in welcher Reihenfolge ich sie dispatchen +sollte. +``` + +--- + +## Danach (laufender Betrieb) + +1. Ready-Set aus `ROADMAP.md` lesen → einen Prompt aus `session-prompts/` nehmen. +2. Frische Session, Modell setzen, dispatchen (Worker bzw. Theorist→Spike). +3. Nach Implement: **Review-Gate** (Opus, kalt) — Prompt-Block in + `session-prompts/TEMPLATE.md`. +4. Merge → Item im Board auf ✅ → Dependents werden frei. Nach N Zyklen: Audit-Loop. diff --git a/session-prompts/TEMPLATE.md b/session-prompts/TEMPLATE.md new file mode 100644 index 0000000..a7aaabe --- /dev/null +++ b/session-prompts/TEMPLATE.md @@ -0,0 +1,77 @@ +# Session-Prompt-Template + +Kopiere diesen Block in eine frische Session. Fülle alle `_…_`-Platzhalter aus. +Jeder Prompt ist **kaltstartfähig** — die neue Session braucht kein Vorwissen. + +--- + +``` +Modell: _Haiku | Sonnet | Opus_ + +Du arbeitest in __ auf einem neuen Branch +`_feat|fix|docs|audit/_` (von `main`). + +## Aufgabe +_Kurze Beschreibung (1–3 Sätze) was implementiert, geprüft oder dokumentiert +werden soll. Scope klar abgrenzen — was liegt AUSSERHALB dieser Session?_ + +## Details +Vollständige Spezifikation in: `__` +Betroffene Dateien: `__` + +## Akzeptanzkriterien +- [ ] _Kriterium 1 (messbar, konkret)_ +- [ ] _Kriterium 2_ +- [ ] Tests grün: `__` + +## Nicht anfassen +_Dateien / Pakete ausserhalb des Scopes. Kein Cross-Editing._ + +## Commit & Push +- Conventional Commit: `_feat|fix|docs|test|chore_: …` +- Trailer: `Co-Authored-By: Claude __ ` +- Push nach `origin`, PR öffnen (Base: `main`). + +## Abschluss +1. Manifest-Eintrag updaten (`manifests/requirements.md` → Status `done`). +2. `STATE.md` aktualisieren (Now / In Progress / Next). +3. Session-Log schreiben (`sessions/TEMPLATE.md` → `sessions/-.md`). +4. Hygiene-Gate ausführen: `bash scripts/gate-session-hygiene.sh`. +5. PR-URL + Test-Zählstand reporten. +``` + +--- + +## Review-Gate-Prompt (Opus, kalt, nach jeder Implement-Session) + +``` +Modell: Opus + +Du bist ein externer Reviewer ohne Vorkontext aus der Implement-Session. +Lies NUR den Diff von Branch `__` gegen `main`. + +Repo: __ +Diff: `git diff main...__` + +## Prüf-Checkliste +- [ ] Build sauber; Test-Suite grün (kein Regressions-Zählstand). +- [ ] Keine bestehenden Tests verändert (außer explizit begründet). +- [ ] Numerische Änderungen sind wert-identisch wo behauptet, oder getestet. +- [ ] Neue Public-Surface (Typen, Enums, API) ist absichtlich und dokumentiert. +- [ ] Commit-Message enthält Model-Attribution des Implementers. +- [ ] Finding / Phase als ✅ in der Orchestration-Tabelle mit Commit-Ref eingetragen. + +## Ergebnis +APPROVE — alles ok. +CHANGES-REQUESTED — konkrete Liste der notwendigen Korrekturen. +``` + +--- + +## Hinweise zum Befüllen + +- **Scope zuerst** — was liegt AUSSERHALB? Das verhindert Scope-Creep. +- **Test-Befehl ist Pflicht** — kein "irgendwie testen", sondern der exakte Aufruf. +- **Model-Routing prüfen** — falsches Modell ist teuer; s. `docs/roles/model-routing.md`. +- **Kein Vorkontext annehmen** — der Prompt landet in einer frischen Session ohne + History. Alle nötigen Pfade, Befehle und Entscheidungen müssen im Prompt stehen. diff --git a/session-prompts/W1.md b/session-prompts/W1.md new file mode 100644 index 0000000..4de37bd --- /dev/null +++ b/session-prompts/W1.md @@ -0,0 +1,41 @@ +# Session-Prompt — W1 Grundgerüst (zuerst, alleine) + +``` +Modell: Sonnet + +Du bist WORKER für Paket W1 in /pfad/zu/jetson-ai-ollama, Branch `feat/w1-scaffold` +(von `main`). Lies zuerst AGENTS.md → STATE.md → CONVENTIONS.md (Projekt-Vertrag). + +## Aufgabe +Das Grundgerüst anlegen, auf das W2–W5 parallel aufsetzen. NUR Struktur + Basis- +Dateien, KEINE Profil-/Exporter-/Client-Logik (das sind W2/W3/W5). + +## Deliverables (deine Dateien) +- `LICENSE` — MIT, auf den Repo-Eigentümer. +- `.env.example` — nur Platzhalter (keine Secrets): + `JETSON_LAN_IP=`, `OLLAMA_MODELS=/opt/ollama/models`, `PROMETHEUS_SCRAPE_TARGET=`. +- Verzeichnis-Skelett mit `.gitkeep`, damit die Parallel-Worker andocken können: + `ollama/systemd/ollama.service.d/`, `exporter/systemd/`, `client/python/jetson_ai/`, + `client/cli/`, `scripts/`, `tests/`, `requirements/`, `docs/`, `models/`. +- `.dvc/config` — leeres DVC-Remote-Skelett mit Kommentar, welches Remote (S3/MinIO/ + SSH/NAS) einzutragen ist. (DVC-Init-Details gehören W2 — hier nur die Datei.) + +## Akzeptanzkriterien +- [ ] `test -f LICENSE && test -f .env.example` +- [ ] `grep -q 'JETSON_LAN_IP=' .env.example` (R-07) +- [ ] Keine echten Werte/Secrets in `.env.example`. +- [ ] Alle Skelett-Verzeichnisse existieren (mit `.gitkeep`). + +## Nicht anfassen +README.md, CONVENTIONS.md, STATE.md, ROADMAP.md, docs/ (außer .gitkeep), und alle +Dateien anderer Pakete. Keine Modelfiles, kein Exporter-Code, kein Client-Code. + +## Abschluss +1. `manifests/requirements.md`: R-07 → `done`. +2. `STATE.md`: W1 nach „In Progress" → nach Merge in „Done"; W2–W5 werden ready. +3. Session-Log aus `sessions/TEMPLATE.md`. +4. Commit `feat(w1): scaffold structure, LICENSE, .env.example` + Trailer + `Co-Authored-By: Claude Sonnet 4.6 `. +5. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`. +6. PR (Base `main`) via Gitea-API. Dann Review-Gate (Opus). +``` diff --git a/session-prompts/W2.md b/session-prompts/W2.md new file mode 100644 index 0000000..ce98596 --- /dev/null +++ b/session-prompts/W2.md @@ -0,0 +1,44 @@ +# Session-Prompt — W2 Ollama-Profile (parallel, nach W1) + +``` +Modell: Sonnet + +Du bist WORKER für Paket W2 in /pfad/zu/jetson-ai-ollama, Branch `feat/w2-profiles` +(von `main`, nach W1-Merge). Lies AGENTS.md → STATE.md → CONVENTIONS.md (Projekt- +Vertrag = Single Source of Truth für Profilnamen, Pfade, Env, num_ctx). + +## Aufgabe +Die drei Ollama-Profile reproduzierbar bauen lassen — über Modelfiles, systemd- +Daemon-Env und ein Build-Skript, mit DVC als Modell-Source-of-Truth. + +## Deliverables (deine Dateien — Ownership: `ollama/`, `scripts/build-models.sh`, `.dvc/`) +- `ollama/Modelfile.light` — `FROM /opt/jetson-ai/models/qwen3.5-4b-q4_k_m.gguf`, + `PARAMETER num_ctx 16384`, `PARAMETER temperature 0.7`. +- `ollama/Modelfile.gemma` — Gemma-4-E4B GGUF, `num_ctx 16384`. +- `ollama/Modelfile.heavy` — Qwen3.5-9B GGUF, `num_ctx 8192`. +- `ollama/systemd/ollama.service.d/override.conf` — exakt die Env aus CONVENTIONS + (FLASH_ATTENTION=1, KV_CACHE_TYPE=q8_0, MAX_LOADED_MODELS=1, KEEP_ALIVE=30s, + MODELS=/opt/ollama/models, HOST=0.0.0.0:11434). +- `scripts/build-models.sh` — `dvc pull` → `ollama create qwen-light -f …light`, + `ollama create gemma -f …gemma`, `ollama create qwen-heavy -f …heavy`. Idempotent. +- `.dvc/config` finalisieren (Remote bleibt env-/platzhaltergesteuert). + +## Akzeptanzkriterien +- [ ] `pytest tests/test_modelfiles.py` grün (W5 liefert den Test; bis dahin lokal: + `grep -q 'num_ctx 16384' ollama/Modelfile.light`). (R-02, R-04) +- [ ] `grep -Eq 'q8_0' ollama/systemd/ollama.service.d/override.conf` und + `grep -q 'MAX_LOADED_MODELS=1'` (R-03). +- [ ] `bash -n scripts/build-models.sh` ok; baut alle drei Profile (R-08). +- [ ] num_ctx in JEDEM Modelfile explizit gesetzt. + +## Nicht anfassen +`exporter/`, `client/`, `tests/`, `scripts/setup-jetson.sh`, `scripts/benchmark.sh`, +`.github/`, `docs/`. Nur deine Ownership-Pfade. + +## Abschluss +1. `manifests/requirements.md`: R-02, R-03, R-04, R-08 → `done`. +2. `STATE.md` + Session-Log aktualisieren. +3. Commit(s) `feat(w2): …` + Trailer `Co-Authored-By: Claude Sonnet 4.6 `. +4. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`. +5. PR (Base `main`). Dann Review-Gate (Opus). +``` diff --git a/session-prompts/W3.md b/session-prompts/W3.md new file mode 100644 index 0000000..26e25a5 --- /dev/null +++ b/session-prompts/W3.md @@ -0,0 +1,39 @@ +# Session-Prompt — W3 Exporter-Sidecar (parallel, nach W1) + +``` +Modell: Sonnet + +Du bist WORKER für Paket W3 in /pfad/zu/jetson-ai-ollama, Branch `feat/w3-exporter` +(von `main`, nach W1-Merge). Lies AGENTS.md → STATE.md → CONVENTIONS.md. + +## Aufgabe +Ollama hat keinen Prometheus-Endpoint. Bau einen schlanken Exporter-Sidecar, der die +Ollama-API anzapft und `/metrics` auf Port 8000 exponiert — als systemd-Service. + +## Deliverables (Ownership: `exporter/`, `requirements/exporter.txt`) +- `exporter/` — Exporter (Python). Quellen: Timing-Felder jeder Ollama-Antwort + (`eval_count`, `eval_duration`, `prompt_eval_duration`, `total_duration`) und + `/api/ps` (Modell, VRAM, Keep-Alive); optional `tegrastats`. Endpoint `:8000/metrics`. + Alternativ einen fertigen Exporter (z. B. `ghcr.io/norskhelsenett/ollama-metrics`) + als systemd-Unit verdrahten — dann ist `exporter/` dünn. +- `exporter/systemd/ollama-exporter.service` — systemd-Unit (After=ollama.service). +- `requirements/exporter.txt` — Laufzeit-Deps des Exporters. + +## Akzeptanzkriterien +- [ ] `pytest tests/test_endpoints.py` deckt den `/metrics`-Smoke ab (W5 liefert den + Test; bis dahin lokal: Exporter startet, `curl :8000/metrics` liefert Prom-Format). (R-06) +- [ ] systemd-Unit ist syntaktisch valide und referenziert Port 8000. +- [ ] Liest NUR die Ollama-API/`/api/ps` — keine Modell-/Profil-Logik (das ist W2). + +## Nicht anfassen +`ollama/`, `client/`, `scripts/`, `.github/`, `docs/`, `tests/`. Nur deine Pfade. +(Den `tests/test_endpoints.py` schreibt W5 — koordiniere die Endpoint-Form über CONVENTIONS.) + +## Abschluss +1. `manifests/requirements.md`: R-06 → `done`. +2. `STATE.md` + Session-Log. +3. Commit `feat(w3): ollama metrics exporter sidecar` + Trailer + `Co-Authored-By: Claude Sonnet 4.6 `. +4. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`. +5. PR (Base `main`). Dann Review-Gate (Opus). +``` diff --git a/session-prompts/W4.md b/session-prompts/W4.md new file mode 100644 index 0000000..c703408 --- /dev/null +++ b/session-prompts/W4.md @@ -0,0 +1,39 @@ +# Session-Prompt — W4 Setup & CI/CD (parallel, nach W1) + +``` +Modell: Sonnet + +Du bist WORKER für Paket W4 in /pfad/zu/jetson-ai-ollama, Branch `feat/w4-setup-cicd` +(von `main`, nach W1-Merge). Lies AGENTS.md → STATE.md → CONVENTIONS.md. + +## Aufgabe +Den Jetson reproduzierbar aufsetzen und CI/CD bereitstellen. + +## Deliverables (Ownership: `scripts/setup-jetson.sh`, `scripts/benchmark.sh`, `.github/workflows/`) +- `scripts/setup-jetson.sh` — Ollama installieren und **GPU-Nutzung verifizieren** + (`ollama ps` + Logs, kein CPU-Fallback); Drop-in-Env aus + `ollama/systemd/ollama.service.d/override.conf` aktivieren (`daemon-reload`, + `restart ollama`); NVMe-SSD + Swap; Desktop-GUI/unnötige Dienste aus; MAXN-SUPER; + Exporter als systemd-Service aktivieren; **Firewall: nur Proxy → 11434**. +- `scripts/benchmark.sh` — Latenz/Token-Durchsatz je Profil (Single-User), `--smoke`-Modus. +- `.github/workflows/ci.yml` — lint + `bash -n` der Skripte + pytest (ohne Jetson-Hardware). +- `.github/workflows/cd-jetson.yml` — Deploy auf den Jetson (self-hosted Runner/SSH). + +## Akzeptanzkriterien +- [ ] `bash -n scripts/setup-jetson.sh` und `bash -n scripts/benchmark.sh` ok (R-05). +- [ ] setup-jetson verifiziert GPU explizit und bindet Ollama nur ans LAN + Firewall. +- [ ] Keine Secrets in den Workflows (nur Repo/Org-Secrets referenzieren). +- [ ] CI läuft ohne Jetson-Hardware grün (Hardware-Schritte als no-op/guarded). + +## Nicht anfassen +`ollama/`, `exporter/`, `client/`, `tests/`, `scripts/build-models.sh`, `docs/`. +Die bereits vorhandene `.github/workflows/gates.yml` (Agent-System-Gates) NICHT ändern. + +## Abschluss +1. `manifests/requirements.md`: R-05 → `done`. +2. `STATE.md` + Session-Log. +3. Commit `feat(w4): jetson setup + ci/cd` + Trailer + `Co-Authored-By: Claude Sonnet 4.6 `. +4. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`. +5. PR (Base `main`). Dann Review-Gate (Opus). +``` diff --git a/session-prompts/W5.md b/session-prompts/W5.md new file mode 100644 index 0000000..dbac055 --- /dev/null +++ b/session-prompts/W5.md @@ -0,0 +1,39 @@ +# Session-Prompt — W5 Client & Tests (parallel, nach W1) + +``` +Modell: Sonnet + +Du bist WORKER für Paket W5 in /pfad/zu/jetson-ai-ollama, Branch `feat/w5-client-tests` +(von `main`, nach W1-Merge). Lies AGENTS.md → STATE.md → CONVENTIONS.md. + +## Aufgabe +Einen schlanken OpenAI-kompatiblen Client + CLI, und die Tests, die die +Erfolgskriterien KODIEREN (damit der Review sie ausführen statt glauben muss). + +## Deliverables (Ownership: `client/`, `tests/`, `requirements/client.txt`, `requirements/dev.txt`) +- `client/python/jetson_ai/client.py` — dünner Wrapper um `/v1/chat/completions` + (Profil per Modellname `qwen-light`/`gemma`/`qwen-heavy`), Type Hints + Docstrings. +- `client/cli/ai.py` — CLI: `ai -m qwen-light "..."`. +- `tests/test_modelfiles.py` — prüft alle drei Modelfiles: `num_ctx` explizit, + korrekte FROM-Pfade, Profilnamen (R-02/R-04-Oracle). +- `tests/test_endpoints.py` — Smoke gegen Ollama `:11434` + Exporter `:8000/metrics` + (gegen laufende Dienste oder gemockt). (R-06/R-10) +- `requirements/client.txt`, `requirements/dev.txt`. + +## Akzeptanzkriterien +- [ ] `pytest tests/ -q` grün (R-09, R-10). +- [ ] `tests/test_modelfiles.py` schlägt fehl, wenn ein `num_ctx` fehlt (negativer Fall). +- [ ] Client spricht die OpenAI-Route, NICHT Ollamas natives `/api/generate`. + +## Nicht anfassen +`ollama/`, `exporter/`, `scripts/`, `.github/`, `docs/`. Nur deine Pfade. Form der +Modelfiles/Endpoints kommt aus CONVENTIONS — bei Unklarheit dort nachsehen, nicht raten. + +## Abschluss +1. `manifests/requirements.md`: R-09, R-10 → `done`. +2. `STATE.md` + Session-Log. +3. Commit `feat(w5): openai client, cli, tests` + Trailer + `Co-Authored-By: Claude Sonnet 4.6 `. +4. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`. +5. PR (Base `main`). Dann Review-Gate (Opus). +``` diff --git a/session-prompts/W6.md b/session-prompts/W6.md new file mode 100644 index 0000000..daa8df9 --- /dev/null +++ b/session-prompts/W6.md @@ -0,0 +1,37 @@ +# Session-Prompt — W6 Docs (zuletzt, integriert die Realität der anderen) + +``` +Modell: Haiku + +Du bist WORKER für Paket W6 in /pfad/zu/jetson-ai-ollama, Branch `docs/w6` +(von `main`, NACHDEM W2–W5 gemerged sind). Lies AGENTS.md → STATE.md → CONVENTIONS.md +und die nun real existierenden Dateien aus W2–W5. + +## Aufgabe +Die Doku schreiben, die den TATSÄCHLICHEN Stand beschreibt (nicht den geplanten), +und README + REVIEW finalisieren. + +## Deliverables (Ownership: `docs/`) +- `docs/architecture.md` — Daemon + Exporter-Sidecar, drei Profile, MAX_LOADED_MODELS=1, + Datenfluss DVC → Ollama. Scope-Grenze (nginx/Prometheus off-box). +- `docs/api.md` — OpenAI-Endpoint, Profilnamen, `/api/ps`, `/metrics`. +- `docs/deployment.md` — `setup-jetson.sh`, `build-models.sh`, Firewall, systemd. +- `docs/troubleshooting.md` — GPU-Fallback erkennen, OOM, Profil lädt nicht, Keep-Alive. +- README-Feinschliff + Verweis aus `REVIEW.md` prüfen (keine toten Links). + +## Akzeptanzkriterien +- [ ] Jede Doku-Aussage deckt sich mit dem realen Code (keine Drift). +- [ ] Alle internen Links lösen auf; `bash scripts/gate-doc-drift.sh` → PASS. +- [ ] Doc-Größenbudget beachtet (< 200 Zeilen je Doc). + +## Nicht anfassen +Code-Pakete (`ollama/`, `exporter/`, `client/`, `scripts/`, `.github/`, `tests/`). +Nur `docs/` + README-Feinschliff. + +## Abschluss +1. Alle verbleibenden `manifests/requirements.md`-Zeilen auf `done` prüfen. +2. `STATE.md`: alles in „Done"; Projekt review-ready. +3. Commit `docs(w6): architecture/api/deployment/troubleshooting` + Trailer + `Co-Authored-By: Claude Haiku 4.5 `. +4. Alle drei Gates grün. PR (Base `main`). Dann Review-Gate (Opus) gegen REVIEW.md. +``` diff --git a/sessions/2026-06-03-bootstrap.md b/sessions/2026-06-03-bootstrap.md new file mode 100644 index 0000000..6a80f3d --- /dev/null +++ b/sessions/2026-06-03-bootstrap.md @@ -0,0 +1,41 @@ +# Session bootstrap — 2026-06-03 + +- **Rolle:** leader +- **Modell:** Opus +- **Ziel:** Projekt aus dem agent-swarm-Template + Jetson-Meta-Prompt bootstrappen + (nur Planung, kein Feature-Code). + +## Geändert (Dateien) +- `ROADMAP.md` — Board W1–W6 als DAG (alle 🧱 infra, kein 🔬 → kein Spike). +- `STATE.md` — Now=Dispatch W1; Ownership-Tabelle W2–W6 (disjunkte Pfade). +- `CONVENTIONS.md` — Projekt-Vertrag (Profilnamen, Pfade, Ports, Daemon-Env, num_ctx, + DVC-SoT, Scope-Grenze). +- `manifests/requirements.md` — R-01…R-10 als kalt verifizierbares Review-Manifest. +- `REVIEW.md` — Kalt-Review-Einstieg (zeigt auf Manifest + Reviewer-Rolle). +- `docs/adr/0002-ollama-native.md` — Architektur-Lock (Ollama-nativ, kein Swapper/Gateway). +- `README.md` — Projekt-Front-Door + „Sofort bauen". +- `session-prompts/W1.md … W6.md` — dispatch-fertige Worker-Prompts. +- `.gitignore` — Jetson-Ignores (`*.gguf`, `models/`, `.dvc/cache/`). +- entfernt: `examples/walkthrough/` (Template-Lernbeispiel; Projekt hat eigenes Board). + +## Entscheidungen +- Ollama-natives Modell-Management statt eigenem Swapper → ADR 0002. +- REVIEW.md (aus Meta-Prompt) = dünner Einstieg; die Kriterien leben im Manifest + (Single Source of Truth, keine Duplikation). + +## Tests +- Gates lokal: hygiene / ownership / doc-drift → PASS (siehe Gates unten). + +## Token-Verbrauch +- (Bootstrap-Session; Planung) — keine Auffälligkeiten. + +## Gates +- Hygiene: PASS · Kontext: PASS · Token: PASS +- Review-Gate: n/a (reine Planung; erste Implement-Session W1 wird gereviewed) + +## Handoff / Next +- **W1 dispatchen** (`session-prompts/W1.md`, Sonnet). Nach Merge: W2–W5 parallel, + dann W6. Ready-Set jetzt = { W1 }. + +## Clean-Start-Check +- [x] Orientierung allein aus AGENTS/STATE/CONVENTIONS möglich. diff --git a/sessions/README.md b/sessions/README.md new file mode 100644 index 0000000..417dcd1 --- /dev/null +++ b/sessions/README.md @@ -0,0 +1,4 @@ +# sessions/ + +Pro Session ein Log aus `TEMPLATE.md`: `YYYY-MM-DD-.md`. Erzählt zusammen mit +dem Git-Log, was passiert ist — inkl. Token-Verbrauch (Eingang fürs Token-Gate). diff --git a/sessions/TEMPLATE.md b/sessions/TEMPLATE.md new file mode 100644 index 0000000..1044cd7 --- /dev/null +++ b/sessions/TEMPLATE.md @@ -0,0 +1,29 @@ +# Session + +- **Rolle:** leader | worker | reviewer | theorist | porter | prototyper | integrator +- **Modell:** Haiku | Sonnet | Opus +- **Ziel:** _…_ + +## Geändert (Dateien) +- _…_ + +## Entscheidungen +- _… (Verweis auf ADR, falls tragend)_ + +## Tests +- _Befehl -> Ergebnis_ + +## Token-Verbrauch +- input: _…_ · output: _…_ · total: _…_ · tokens/Task: _…_ +- Auffälligkeiten (Re-Reading, Schleifen): _…_ + +## Gates +- Hygiene: PASS/FAIL · Kontext: PASS/FAIL · Token: PASS/FAIL +- Review-Gate: APPROVE / CHANGES-REQUESTED (Opus-Session-ID: _…_) + +## Handoff / Next +- _Was die nächste Session zuerst tun sollte._ +- Review-Gate nötig? Ja/Nein + +## Clean-Start-Check +- [ ] Orientierung allein aus AGENTS/STATE/CONVENTIONS möglich.