pi_coder/CLAUDE.md
dschlueter cba70b67a1 docs: neue Flags, Quick-Judge und parallele Server-Checks dokumentiert
- --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>
2026-05-29 18:08:00 +02:00

5.4 KiB
Raw Blame History

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, ~13 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:

  1. writeTaskMd() → TASK.md anlegen
  2. --continue-Modus: Coder- und Judge-Server parallel via Promise.all(waitUntilModelReady×2) prüfen
  3. Coder: coderKickoff() → implementiert + committet
  4. Äußere while(keepGoing)-Schleife (für --interactive-Zusatzaufträge)
  5. 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
  6. Bei PASS + --interactive: Polling auf interactiveContinueRequested. Zusatzauftrag → coderKickoff()keepGoing = true
  7. SHIP-Schritt: PASS oder (PASS WITH CONCERNS + --approve-concerns) → direkt SHIP. PASS WITH CONCERNS sonst → shipitPrompt() → SHIP/NO-SHIP
  8. Loop-Erkennung: normalizeForComparison(currentBlockers) === normalizeForComparison(lastBlockers) → Abbruch
  9. 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

  • cancelRequested ist eine modulare Variable — sie wird von /cancel gesetzt und nach jedem Loop-Schritt in /optimize geprüft und zurückgesetzt.
  • currentModelKey — Cache für switchModel(): speichert "provider/modelId" des zuletzt gesetzten Modells. Bei identischem Key wird pi.setModel() übersprungen. Wird im finally-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 mit judgePrompt().
  • interactivePauseActive / interactiveContinueRequested / interactivePauseTask — drei modulare Variablen für den --interactive-Modus. interactivePauseActive wird vom /continue-Command geprüft, um zwischen Interactive-Pause-Signal und normalem Fortsetzen zu unterscheiden. Alle drei werden im finally-Block zurückgesetzt.
  • sendAndWait() wartet erst auf idle, dann deliverAs: "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".