- --no-tests und --approve-concerns in Syntax, Beschreibungen und Beispielen - Quick-Check für Runde 1 im Ablaufbeispiel erklärt - --continue: Hinweis auf parallele Server-Bereitschaftsprüfung - Abschnitt 11 (Anwendungsfälle): neue Beispiele für --no-tests / --approve-concerns - CLAUDE.md: currentModelKey-Cache, normalizeForComparison, quickJudgePrompt dokumentiert Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.4 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Was ist dieses Repo?
Eine TypeScript-Extension für den pi-Coding-Agent (@earendil-works/pi-coding-agent). Sie implementiert einen automatisierten Coder → Judge → Fix-Loop mit zwei lokalen llama.cpp-Servern.
Nach jeder Änderung an pi-coder-judge-extension.ts oder models.json muss deployed werden:
./install.sh # kopiert nach ~/.pi/agent/extensions/ und ~/.pi/agent/
# dann in pi agent: /reload
Server-Lifecycle
./start-servers.sh # beide Container parallel starten (empfohlen, ~1–3 min)
./start-coder.sh # nur Coder :8001
./start-judge.sh # nur Judge :8002
./stop-servers.sh # beide stoppen
./status.sh # Container- und HTTP-Status beider Server
Die Start-Skripte stoppen existierende Container automatisch vor dem Neustart.
Architektur der Extension
pi-coder-judge-extension.ts ist die einzige Logikdatei. Sie registriert alle Commands, das apply_patch-Custom-Tool und zwei Event-Hooks beim pi-Agent.
Zwei LLM-Rollen:
| Rolle | Port | Container | Alias |
|---|---|---|---|
| Coder (Implementierung, Fixes, Doku) | 8001 | qwen36-27b-coder |
qwen3.5-coder |
| Judge (Review, ShipIt, QuickCheck) | 8002 | qwen36-27b-judge |
qwen3.5-judge |
Beide nutzen dasselbe GGUF (Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.gguf), aber unterschiedliche Serverparameter.
Zentraler Ablauf in /optimize:
writeTaskMd()→ TASK.md anlegen--continue-Modus: Coder- und Judge-Server parallel viaPromise.all(waitUntilModelReady×2)prüfen- Coder:
coderKickoff()→ implementiert + committet - Äußere
while(keepGoing)-Schleife (für--interactive-Zusatzaufträge) - Loop (max. N Runden, Standard 2):
- Runde 1 (ohne
--continue):quickJudgePrompt()/quickJudgeWithTestsPrompt()— kurzer Erstcheck - Runde 2+:
judgePrompt()/judgeWithTestsPrompt()— vollständige Analyse mit TASK.md parseVerdict()→ PASS? → break. FAIL? →parseBlockers()→normalizeForComparison()→ Loop-Check → Fix → nächste Runde
- Runde 1 (ohne
- Bei PASS +
--interactive: Polling aufinteractiveContinueRequested. Zusatzauftrag →coderKickoff()→keepGoing = true - SHIP-Schritt:
PASSoder (PASS WITH CONCERNS+--approve-concerns) → direkt SHIP.PASS WITH CONCERNSsonst →shipitPrompt()→ SHIP/NO-SHIP - Loop-Erkennung:
normalizeForComparison(currentBlockers) === normalizeForComparison(lastBlockers)→ Abbruch - Optional:
runUpdateDoku()bei--with-doku
tool_call-Hook (edit-Reordering): Sortiert Multi-Edit-Aufrufe auf dieselbe Datei von hinten nach vorne. Verhindert den Fehler „edits[n] doesn't match" wenn mehrere Stellen einer Datei auf einmal geändert werden.
apply_patch-Tool: Wendet unified diffs via patch -p1 an — robuster als mehrfache edit-Aufrufe bei umfangreichen Änderungen.
Inkrementelle Dokumentation (runUpdateDoku): Git-Tags (docs-last-commented, docs-last-readme, docs-last-bedienungsanleitung) markieren den letzten Dokumentationslauf. Nur Dateien, die sich seitdem geändert haben, werden neu verarbeitet.
Modell-Konfiguration (models.json)
Fünf Provider: ollama (lokale Ollama-Instanz), llama-cpp (:8000), llama-cpp-coder (:8001), llama-cpp-judge (:8002), openrouter. Die beiden llama-cpp-*-Provider werden von der Extension via switchModel() automatisch gewechselt — nie manuell setzen wenn die Extension läuft.
Kritische Felder bei llama-cpp-Providern: contextWindow muss mit dem -c-Parameter im Start-Skript übereinstimmen (aktuell 262144). maxTokens begrenzt die Ausgabelänge pro Request.
Wichtige Invarianten
cancelRequestedist eine modulare Variable — sie wird von/cancelgesetzt und nach jedem Loop-Schritt in/optimizegeprüft und zurückgesetzt.currentModelKey— Cache fürswitchModel(): speichert"provider/modelId"des zuletzt gesetzten Modells. Bei identischem Key wirdpi.setModel()übersprungen. Wird imfinally-Block auf""resettet.normalizeForComparison(s)— Hilfsfunktion für die Loop-Erkennung: normalisiert Whitespace und Satzzeichen vor dem String-Vergleich, verhindert False-Negatives.quickJudgePrompt()/quickJudgeWithTestsPrompt()— kompakte Prompt-Varianten für Runde 1 (ohne--continue): kein TASK.md, nur Diff + Testergebnis. Bei FAIL folgt Runde 2 mitjudgePrompt().interactivePauseActive/interactiveContinueRequested/interactivePauseTask— drei modulare Variablen für den--interactive-Modus.interactivePauseActivewird vom/continue-Command geprüft, um zwischen Interactive-Pause-Signal und normalem Fortsetzen zu unterscheiden. Alle drei werden imfinally-Block zurückgesetzt.sendAndWait()wartet erst aufidle, danndeliverAs: "followUp"— verhindert „Agent is already processing".tickTaskMdStatus()nutzt Python3 für den String-Ersatz in TASK.md (kein Shell-Escaping-Problem).- Beide Start-Skripte warten bis zu 90×2 s auf HTTP-Erreichbarkeit und führen dann einen Smoke-Test-Completion durch.
GPU-Setup
Hardware: 2× RTX 3090 (device=1,2), tensor-split 0.5,0.5. KV-Cache: q4_0 (25 % des fp16-VRAM — nötig für 262k Kontext auf 2× 24 GB). Für andere GPU-Konfigurationen: README.md Abschnitt „Anpassung".