From d5dc7f36b350dd5abd2012a1afba59b0410f318e Mon Sep 17 00:00:00 2001 From: Tarik Moussa Date: Wed, 3 Jun 2026 23:29:56 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20scope-fix=20=E2=80=94=20Jetson=20extern?= =?UTF-8?q?,=20F-02-Spike=20entfernt,=20DAG=20vereinfacht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Modell-Server ist externer Dienst. F-05 portiert direkt gegen OpenAI-compat API (MODEL_BASE_URL konfigurierbar). ADR-0004 aktualisiert. F-03/F-04/F-05 werden nach F-01 parallel frei. Co-Authored-By: Claude Sonnet 4.6 --- ROADMAP.md | 21 ++++---- STATE.md | 16 +++--- docs/adr/0004-modell-api-spike-first.md | 31 ++++++----- manifests/requirements.md | 7 ++- session-prompts/F-02-api-spike.md | 69 ------------------------- 5 files changed, 36 insertions(+), 108 deletions(-) delete mode 100644 session-prompts/F-02-api-spike.md diff --git a/ROADMAP.md b/ROADMAP.md index 23a5279..aabcc74 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -29,30 +29,27 @@ Ready-Set = { Items mit Status 🔲, deren Prereqs ALLE ✅ sind } F-01 (Skeleton) ──┬──► F-03 (Whitelist) ──┐ ├──► F-04 (Bot-Handler) ──┼──► F-06 (Integration) ──► F-07 (Deploy) └──► F-05 (Model-Connector) ──┘ -F-02 (API-Spike) ──► F-05 ``` -> F-02 ist 🔬: Spike-Gate muss durch, bevor F-05 dispatcht wird. -> F-05 bleibt ⏸ bis F-01 **und** F-02 ✅ sind. -> F-06 bleibt ⏸ bis F-03, F-04 **und** F-05 ✅ sind. -> F-07 bleibt ⏸ bis F-06 ✅ ist. +> Nach F-01 ✅ werden F-03, F-04 und F-05 **gleichzeitig** frei — alle drei +> können parallel dispatcht werden. +> F-06 bleibt ⏸ bis F-03 + F-04 + F-05 alle ✅ sind. ## Board | ID | Item | Typ | Status | Prereqs | Rolle · Modell | Aufwand | |----|------|-----|--------|---------|----------------|---------| | F-01 | Projekt-Skeleton (pyproject.toml, Paketstruktur, CI-Stub) | 🧱 | 🔲 | — | Worker · Sonnet | ~0.5 d | -| F-02 | Spike: Modell-API-Format (welches Endpoint-Schema exponiert der Jetson-Server?) | 🔬 | 🔲 | — | Theorist · Opus → Spike | ~0.5 d | | F-03 | Whitelist-Middleware (User-ID-Allowlist, Env-Var-Config) | 🧱 | ⏸ | F-01 | Worker · Sonnet | ~0.5 d | | F-04 | Telegram-Bot-Handler (Polling-Loop, /start, /help, Nachricht-Relay) | 🔌 | ⏸ | F-01 | Porter · Sonnet | ~1 d | -| F-05 | Modell-HTTP-Connector (async httpx-Client zum lokalen Modell-Server) | 🔌 | ⏸ | F-01, F-02 | Porter · Sonnet | ~0.5 d | +| F-05 | Modell-HTTP-Connector (httpx-Client gegen konfigurierbaren OpenAI-compat Endpoint) | 🔌 | ⏸ | F-01 | Porter · Sonnet | ~0.5 d | | F-06 | Integration & Smoke-Test (Whitelist + Handler + Connector verdrahtet, E2E-Test) | 🧱 | ⏸ | F-03, F-04, F-05 | Worker · Sonnet | ~1 d | -| F-07 | Deployment-Config (.env.example, Docker oder systemd-Unit für Jetson) | 🧱 | ⏸ | F-06 | Worker · Haiku | ~0.5 d | +| F-07 | Deployment-Config (.env.example, Docker oder systemd-Unit) | 🧱 | ⏸ | F-06 | Worker · Haiku | ~0.5 d | -> F-02 ist `🔬`: vor Produktionscode erst **Spike** (`docs/loops/spike-gate.md`) — -> Nachweis, dass wir den Modell-Server erfolgreich ansprechen können (Connectivity-GO). -> F-04 ist `🔌`: Referenz-Impl = python-telegram-bot-v21-Doku (golden oracle vorhanden). -> F-05 ist `🔌`: Referenz-Impl entsteht aus F-02-Spike-Spec. +> F-04 ist `🔌`: Referenz-Impl = python-telegram-bot-v21-Dokumentation (golden oracle vorhanden). +> F-05 ist `🔌`: Referenz-Impl = OpenAI Chat Completions API (de-facto-Standard für +> selbst gehostete Modelle; Endpoint-URL ist reine Config, kein Forschungsproblem). +> ADR-0004 begründet, warum kein Spike nötig ist. ## Done | ID | Item | Session | Commit | diff --git a/STATE.md b/STATE.md index 9a3c94e..1bb4b28 100644 --- a/STATE.md +++ b/STATE.md @@ -5,28 +5,26 @@ **Letzte Session:** S-BOOTSTRAP / 2026-06-03 · **Aktive Rolle:** leader ## Now (in dieser Session im Fokus) -- Bootstrap-Planning: ROADMAP befüllt, ADRs angelegt, Session-Prompts für F-01 und F-02 erzeugt. +- Scope-Korrektur: Jetson/Modell-Server ist extern — F-02-Spike entfernt, DAG vereinfacht. ## In Progress (begonnen, nicht fertig) -- _(keine — Bootstrap ist abgeschlossen, nächste Dispatch-Sessions stehen bereit)_ +- _(keine — bereit zum Dispatch)_ ## Blocked - F-03 Whitelist — wartet auf F-01 (`⏸`). - F-04 Bot-Handler — wartet auf F-01 (`⏸`). -- F-05 Model-Connector — wartet auf F-01 + F-02 (`⏸`). -- F-06 Integration — wartet auf F-03, F-04, F-05 (`⏸`). +- F-05 Model-Connector — wartet auf F-01 (`⏸`). +- F-06 Integration — wartet auf F-03 + F-04 + F-05 (`⏸`). - F-07 Deployment — wartet auf F-06 (`⏸`). ## Next (priorisiert) -1. F-01 dispatchen (Worker · Sonnet) — `session-prompts/F-01-skeleton.md`. -2. F-02 dispatchen (Theorist · Opus → Spike-Gate) — `session-prompts/F-02-api-spike.md`. - Beide können **parallel** starten, da kein Prereq zwischen ihnen. +1. **F-01** dispatchen (Worker · Sonnet) — `session-prompts/F-01-skeleton.md`. +2. Nach F-01 ✅: F-03, F-04, F-05 können **parallel** dispatcht werden. ## Offene Audit-Findings -- _(keine — Projekt frisch gestartet)_ +- _(keine)_ ## Datei-Ownership (aktiv) | Paket | Dateien/Pfade | Owner | |---|---|---| | skeleton | `pyproject.toml`, `src/`, `tests/` | worker-F01 | -| spike-api | `spike/model-api/` | theorist-F02 | diff --git a/docs/adr/0004-modell-api-spike-first.md b/docs/adr/0004-modell-api-spike-first.md index 7610ece..acabfc0 100644 --- a/docs/adr/0004-modell-api-spike-first.md +++ b/docs/adr/0004-modell-api-spike-first.md @@ -1,15 +1,18 @@ -# 0004 — Modell-API-Format: erst Spike, dann Connector +# 0004 — Modell-Connector gegen OpenAI-kompatible API, kein Spike nötig -- **Status:** accepted -- **Kontext:** Der Jetson Orin Nano Super hostet ein lokales Modell. Das - Endpoint-Schema ist nicht festgelegt (mögliche Backends: Ollama, - llama.cpp-HTTP-Server, vLLM, custom FastAPI). Kein golden oracle. -- **Entscheidung:** F-02 (🔬 Spike) läuft **vor** F-05 (🔌 Connector). - Der Spike bestimmt das tatsächliche API-Schema und erzeugt eine - Mini-Spec (`spike/model-api/spec.md`). F-05 portiert gegen diese Spec. -- **GO-Kriterium:** Python-Skript sendet eine Test-Nachricht und empfängt - eine nicht-leere Antwort vom lokalen Server. Latenz < 30 s akzeptabel. -- **NO-GO-Kriterium:** Kein Endpoint erreichbar oder Antwort-Format - vollständig undokumentiert → Human-Entscheid, welcher Backend aufzusetzen. -- **Konsequenz:** F-05 bleibt ⏸ bis Spike ✅ + GO. Wenn NO-GO: ⛔ blocked-extern. - Spike-Branch `spike/model-api` wird nach GO verworfen; Spec bleibt in `docs/`. +- **Status:** accepted (ersetzt: 2026-06-03, vorherige Version sah Spike vor) +- **Kontext:** Der selbst gehostete Modell-Server (Jetson Orin Nano Super) ist + ein **externer Dienst** außerhalb dieses Repos. Das Backend (Ollama, llama.cpp, + vLLM o. ä.) ist Sache des Betreibers, nicht dieses Projekts. +- **Entscheidung:** Der Connector (F-05) portiert gegen die **OpenAI Chat + Completions API** (`POST /v1/chat/completions`). Das ist der de-facto-Standard + für selbst gehostete Modelle. Die Basis-URL wird via Env-Var `MODEL_BASE_URL` + konfiguriert. Kein Spike nötig — die API-Spec ist bekannt und stabil. +- **Gründe:** + - Ollama, llama.cpp-HTTP, vLLM und LiteLLM exponieren alle diese Schnittstelle. + - Der Connector funktioniert mit jedem Backend, das sich daran hält. + - Ein Spike wäre nur nötig, wenn das API-Format unbekannt wäre — das ist hier + nicht der Fall. +- **Konsequenz:** Wenn der externe Server ein nicht-kompatibles Format hat, + ist das ein Ops-Problem, kein Code-Problem. F-05 dokumentiert das erwartete + Schema im Manifest (R-0006). diff --git a/manifests/requirements.md b/manifests/requirements.md index c897cc0..fb49194 100644 --- a/manifests/requirements.md +++ b/manifests/requirements.md @@ -9,10 +9,9 @@ Eine Zeile je Erfolgskriterium. Der Reviewer prüft Spalte für Spalte. | R-0003 | Ruff meldet 0 Befunde | `src/`, `tests/` | `uv run ruff check src/ tests/` | todo | | R-0004 | Bot antwortet nur auf whitelistete User-IDs | `src/bot/whitelist.py` | `uv run pytest tests/test_whitelist.py -v` | todo | | R-0005 | Nicht-whitelistete User erhalten keine Antwort | `src/bot/whitelist.py` | `uv run pytest tests/test_whitelist.py::test_blocked_user -v` | todo | -| R-0006 | Bot leitet Nachrichten an lokales Modell weiter | `src/bot/connector.py` | `uv run pytest tests/test_connector.py -v` | todo | +| R-0006 | Connector sendet POST /v1/chat/completions an MODEL_BASE_URL | `src/bot/connector.py` | `uv run pytest tests/test_connector.py -v` | todo | | R-0007 | Modell-Antwort wird an User zurückgesendet | `src/bot/handlers.py` | `uv run pytest tests/test_handlers.py -v` | todo | -| R-0008 | Spike-Ergebnis: Modell-API erreichbar (GO) | `spike/model-api/result.md` | manuell: `python spike/model-api/probe.py` | todo | -| R-0009 | Config lädt aus Env-Vars ohne Exception | `src/bot/config.py` | `uv run pytest tests/test_config.py -v` | todo | -| R-0010 | `.env` nicht im Git-Index | `.gitignore` | `git ls-files .env` → leer | todo | +| R-0008 | Config lädt aus Env-Vars ohne Exception | `src/bot/config.py` | `uv run pytest tests/test_config.py -v` | todo | +| R-0009 | `.env` nicht im Git-Index | `.gitignore` | `git ls-files .env` → leer | todo | Status: `todo` · `in_progress` · `done` · `drift` (vom Audit markiert). diff --git a/session-prompts/F-02-api-spike.md b/session-prompts/F-02-api-spike.md deleted file mode 100644 index 5d76a52..0000000 --- a/session-prompts/F-02-api-spike.md +++ /dev/null @@ -1,69 +0,0 @@ -# Session-Prompt F-02 — Spike: Modell-API-Format (Theorist + Prototyper) - -``` -Modell: Opus - -Du arbeitest in /Users/tarikmoussa/Desktop/files/agent-swarm-repo auf einem neuen Branch -`spike/model-api` (von `main`). - -WICHTIG: Dies ist ein Research-Spike. Der Branch ist Wegwerf. Kein Produktionscode. -Spike-Gate-Regeln: `docs/loops/spike-gate.md` -ADR: `docs/adr/0004-modell-api-spike-first.md` - -## Aufgabe -Bestimme das API-Format des selbst gehosteten Sprachmodells auf dem Jetson Orin Nano Super -und produziere eine Mini-Spec (`spike/model-api/spec.md`), gegen die F-05 dann portiert. - -Hintergrund: Das Modell läuft auf einem lokalen Server. Der wahrscheinlichste -Backend-Stack ist **Ollama** (exponiert eine OpenAI-kompatible API auf Port 11434) -oder **llama.cpp HTTP-Server** (Port 8080, eigenes Format). Wir wissen es nicht sicher. - -## Phase 1 — Theorist (du selbst, Opus) -1. Liste die drei wahrscheinlichsten Backend-Optionen für Jetson Orin: - - Ollama (`/api/generate`, `/api/chat` oder OpenAI-compat `/v1/chat/completions`) - - llama.cpp HTTP (`/completion`) - - Custom FastAPI -2. Für jede Option: notiere das minimale Request-/Response-Schema (JSON). -3. Schreibe `spike/model-api/spec.md` mit den Schema-Varianten und dem - GO-Kriterium: "Antwort ist nicht-leer und unter 30 s". - -## Phase 2 — Prototyper (du selbst, Opus) -Schreibe `spike/model-api/probe.py` — ein minimales, wegwerfbares Python-Skript: -- Liest MODEL_BASE_URL aus Env-Var (default: http://localhost:11434). -- Schickt eine kurze Test-Nachricht ("Hallo, antworte mit einem Wort."). -- Gibt die rohe JSON-Antwort aus. -- Kommentiert, welches Schema es probiert hat. - -Das Skript ist **kein Produktionscode** — kein Error-Handling, keine Abstraktionen. - -## Phase 3 — GO/NO-GO -Dokumentiere in `spike/model-api/result.md`: -- Welches Backend hast du vorgefunden (oder angenommen)? -- Funktioniert der Probe erfolgreich? (GO / NO-GO) -- Exaktes API-Schema für den Connector (Request + Response-Felder). -- Empfehlung für F-05 Porter (welche Library, welchen Endpoint). - -## Akzeptanzkriterien -- [ ] `spike/model-api/spec.md` enthält ≥ 2 Schema-Varianten mit JSON-Beispielen. -- [ ] `spike/model-api/probe.py` läuft ohne Import-Fehler (`python spike/model-api/probe.py --help` o. ä.). -- [ ] `spike/model-api/result.md` enthält ein klares GO oder NO-GO mit Begründung. -- [ ] GO: Das finale API-Schema ist in `result.md` exakt spezifiziert (Felder, Typen, Endpoint-Pfad). -- [ ] NO-GO: Ursache dokumentiert + Human-Empfehlung, welches Backend aufzusetzen. - -## Nicht anfassen -`src/`, `tests/`, `pyproject.toml`, `ROADMAP.md`, `STATE.md` — alles außer `spike/model-api/`. -Kein Produktionscode schreiben. Spike-Branch wird nach GO verworfen. - -## Commit & Push -- Conventional Commit: `docs: spike model-api format discovery [GO/NO-GO]` -- Trailer: `Co-Authored-By: Claude Opus 4.7 ` -- Push nach `origin spike/model-api`. -- Kein PR — Leader entscheidet nach GO/NO-GO über nächsten Schritt. - -## Abschluss -1. `STATE.md` aktualisieren: F-02 Spike-Ergebnis + GO/NO-GO eintragen. -2. Falls GO: Leader dispatcht F-05 (Porter · Sonnet) mit `result.md` als Spec. - Falls NO-GO: Leader markiert F-05 als ⛔ blocked-extern + Human-Eskalation. -3. Session-Log: `sessions/F-02-.md`. -4. Hygiene-Gate: `bash scripts/gate-session-hygiene.sh`. -```