feat: bootstrap jetson-ai-ollama from agent-swarm template
Some checks failed
gates / quality (push) Has been cancelled

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 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 06:55:39 +02:00
commit efee259d01
43 changed files with 1563 additions and 0 deletions

View File

@@ -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 _<absoluter Repo-Pfad>_.
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. 315 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 '<id / datum>'-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/<ID>.md aus
session-prompts/TEMPLATE.md erzeugen — Modell gemäß docs/roles/model-routing.md.
5. Ein Session-Log unter sessions/<datum>-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 <noreply@anthropic.com>`.
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.

View File

@@ -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 _<absoluter Pfad zum Repo>_ auf einem neuen Branch
`_feat|fix|docs|audit/<name>_` (von `main`).
## Aufgabe
_Kurze Beschreibung (13 Sätze) was implementiert, geprüft oder dokumentiert
werden soll. Scope klar abgrenzen — was liegt AUSSERHALB dieser Session?_
## Details
Vollständige Spezifikation in: `_<Pfad zum Detail-Dokument>_`
Betroffene Dateien: `_<Pfad(e)>_`
## Akzeptanzkriterien
- [ ] _Kriterium 1 (messbar, konkret)_
- [ ] _Kriterium 2_
- [ ] Tests grün: `_<Test-Befehl>_`
## Nicht anfassen
_Dateien / Pakete ausserhalb des Scopes. Kein Cross-Editing._
## Commit & Push
- Conventional Commit: `_feat|fix|docs|test|chore_: …`
- Trailer: `Co-Authored-By: Claude _<Modell>_ <noreply@anthropic.com>`
- 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/<id>-<datum>.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 `_<branch>_` gegen `main`.
Repo: _<absoluter Pfad>_
Diff: `git diff main..._<branch>_`
## 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.

41
session-prompts/W1.md Normal file
View File

@@ -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 W2W5 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"; W2W5 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 <noreply@anthropic.com>`.
5. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`.
6. PR (Base `main`) via Gitea-API. Dann Review-Gate (Opus).
```

44
session-prompts/W2.md Normal file
View File

@@ -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 <noreply@anthropic.com>`.
4. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`.
5. PR (Base `main`). Dann Review-Gate (Opus).
```

39
session-prompts/W3.md Normal file
View File

@@ -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 <noreply@anthropic.com>`.
4. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`.
5. PR (Base `main`). Dann Review-Gate (Opus).
```

39
session-prompts/W4.md Normal file
View File

@@ -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 <noreply@anthropic.com>`.
4. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`.
5. PR (Base `main`). Dann Review-Gate (Opus).
```

39
session-prompts/W5.md Normal file
View File

@@ -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 <noreply@anthropic.com>`.
4. `bash scripts/gate-session-hygiene.sh && bash scripts/gate-ownership.sh`.
5. PR (Base `main`). Dann Review-Gate (Opus).
```

37
session-prompts/W6.md Normal file
View File

@@ -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 W2W5 gemerged sind). Lies AGENTS.md → STATE.md → CONVENTIONS.md
und die nun real existierenden Dateien aus W2W5.
## 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 <noreply@anthropic.com>`.
4. Alle drei Gates grün. PR (Base `main`). Dann Review-Gate (Opus) gegen REVIEW.md.
```