diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index f4c3433..54b414d 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -32,11 +32,16 @@ eine andere Persona annimmt: sie, führt Tests aus und erstellt Git-Commits. **Judge-Persona**: Überprüft den Code mit dem Blick eines skeptischen Senior-Entwicklers. -Prüft Korrektheit, Robustheit, Randfälle, Sicherheit und Produktionsreife. Gibt ein Urteil: -- `PASS` — Code ist in Ordnung -- `PASS WITH CONCERNS` — hat Anmerkungen, die behoben werden müssen (wird wie `FAIL` behandelt, - außer du verwendest `--approve-concerns`) -- `FAIL` — enthält Blocker, die behoben werden müssen +Prüft Korrektheit, Robustheit, Randfälle, Sicherheit und Produktionsreife. Maßstab für das Urteil +sind `TASK.md` und, falls vorhanden, `SPEC.md`: +- `PASS` — alle Anforderungen erfüllt, Tests grün, kein Blocker und kein Major +- `PASS WITH CONCERNS` — alle Anforderungen erfüllt, aber mindestens ein Major: ein konkretes Risiko im + geforderten Einsatz, mit Reproduktion (wird wie `FAIL` behandelt, außer du verwendest `--approve-concerns`) +- `FAIL` — eine Anforderung fehlt, Tests schlagen fehl oder ein reproduzierbarer Fehler im geforderten Verhalten + +Härtung über die Anforderungen hinaus, Skalierung, Stil und Wünsche schreibt der Judge unter „Hinweise“. Sie +ändern das Urteil nicht, und der Coder bearbeitet sie bei `/fix` nicht. Ein Major ohne Reproduktion gilt als +Hinweis. Ohne diese Regeln urteilte der Judge mit Strata am 15.10.2026 in keiner Aufgabe PASS. Die Umschaltung zwischen den Rollen erfolgt über unterschiedliche System-Prompts, die die Extension automatisch vor jeder Inference einsetzt. Es läuft kein zweiter Server. @@ -249,21 +254,22 @@ Urteil: PASS WITH CONCERNS Blocker: keine Major: -- Stoppwortliste ist hardcoded; große Projekte erwarten --stopwords-file Option +- Nicht-existente Datei: Traceback statt Meldung und Exit-Code 2 (TASK.md verlangt Exit 2). + Reproduktion: python3 textcount.py fehlt.txt; echo $? → Traceback, Exit 1 Minor: -- Keine --version Flag -- Fehlermeldung bei nicht-existenter Datei gibt keinen Exit-Code 1 zurück +- Fehlermeldung nennt den Dateinamen nicht Fehlende Tests: - Test für leere Datei fehlt - Test für Datei mit nur Leerzeichen fehlt -Produktionsrisiken: +Hinweise (ändern das Urteil nicht): - Bei sehr großen Dateien (>1 GB) wird alles in den RAM geladen +- Keine --version Flag Konkrete Fix-Aufträge: -1. exit(1) bei FileNotFoundError +1. FileNotFoundError abfangen, Meldung mit Dateiname, exit(2) 2. Test für leere Eingabedatei ``` diff --git a/README.md b/README.md index 387fdcd..61fab41 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,9 @@ einen weiteren Fix-Auftrag, genau wie bei `FAIL`. Erst sauberes `PASS` beendet d Opt-out: `--approve-concerns` lässt `PASS WITH CONCERNS` als bestanden gelten. +Wann der Judge welches Urteil gibt (Urteilsregeln, Abschnitt „Hinweise“): siehe +[BEDIENUNGSANLEITUNG.md](BEDIENUNGSANLEITUNG.md), Judge-Persona. + --- ## Live-Aktivitätsstatus diff --git a/pi-coding-extension.ts b/pi-coding-extension.ts index 0ac81a4..d610921 100644 --- a/pi-coding-extension.ts +++ b/pi-coding-extension.ts @@ -51,6 +51,28 @@ function coderKickoff(task: string): string { ].join("\n"); } +// Urteilsregeln und Ausgabeformat beider Judge-Prompts. Ohne feste Regeln fand der Judge (Strata, 15.10.) in jeder +// Runde neue Härtungen über die Anforderungen hinaus und urteilte nie PASS, auch bei erfüllter SPEC. +function judgeVerdictSection(): string[] { + return [ + "Urteilsregeln (verbindlich; Maßstab ist TASK.md und, falls vorhanden, SPEC.md):", + "- FAIL: eine Anforderung ist nicht erfüllt, Tests schlagen fehl, oder ein reproduzierbarer Fehler im geforderten Verhalten.", + "- PASS WITH CONCERNS: alle Anforderungen erfüllt, aber mindestens ein Major: ein konkretes Risiko im geforderten Einsatz, mit Reproduktion (Befehl oder Eingabe → falsches Ergebnis).", + "- PASS: alle Anforderungen erfüllt, Tests grün, kein Blocker und kein Major. Minor-Punkte und Hinweise ändern daran nichts.", + "- Härtung über die Anforderungen hinaus, Skalierung, Stil, Wünsche und Risiken in nicht geforderten Umgebungen gehören unter „Hinweise“. Sie ändern das Urteil nicht und sind keine Fix-Aufträge.", + "- Ein Major ohne Reproduktion ist ein Hinweis.", + "", + "Ausgabeformat:", + "- Urteil: PASS | PASS WITH CONCERNS | FAIL", + "- Blocker", + "- Major", + "- Minor", + "- Fehlende Tests", + "- Hinweise (ändern das Urteil nicht)", + "- Konkrete Fix-Aufträge an den Coder (nur für Blocker, Major, Minor und fehlende Tests)", + ]; +} + function judgePrompt(extra: string): string { const suffix = extra?.trim() ? "\n\nZusätzlicher Fokus des Users:\n" + extra.trim() : ""; return [ @@ -65,14 +87,7 @@ function judgePrompt(extra: string): string { "4. Bewerte Korrektheit, Robustheit, Fehlerbehandlung, Sicherheit, Logging, Wartbarkeit und Produktionsreife.", "5. Wenn etwas fehlt, sage es klar und direkt.", "", - "Ausgabeformat:", - "- Urteil: PASS | PASS WITH CONCERNS | FAIL", - "- Blocker", - "- Major", - "- Minor", - "- Fehlende Tests", - "- Produktionsrisiken", - "- Konkrete Fix-Aufträge an den Coder", + ...judgeVerdictSection(), "", "Wenn du etwas behauptest, nenne die Datei, den Befehl, den Test oder den Reproduktionshinweis." ].join("\n") + suffix; @@ -98,14 +113,7 @@ function judgeWithTestsPrompt(testOutput: string, extra: string): string { "3. Versuche weitere Fehler im Code aktiv zu finden (Randfälle, Sicherheit, Robustheit).", "4. Wenn du etwas behauptest, nenne die Datei, die Zeile oder den Reproduktionshinweis.", "", - "Ausgabeformat:", - "- Urteil: PASS | PASS WITH CONCERNS | FAIL", - "- Blocker", - "- Major", - "- Minor", - "- Fehlende Tests", - "- Produktionsrisiken", - "- Konkrete Fix-Aufträge an den Coder", + ...judgeVerdictSection(), ].join("\n") + suffix; } @@ -115,7 +123,7 @@ function fixPrompt(extra: string): string { "Wechsle in den Reparaturmodus.", "Lies TASK.md als Referenz — stelle sicher, dass nach den Fixes alle Anforderungen erfüllt bleiben.", "Nutze den letzten Judge-Bericht als verbindliche Aufgabenliste.", - "Behebe zuerst Blocker, dann Major, dann Minor.", + "Behebe zuerst Blocker, dann Major, dann Minor. Der Abschnitt „Hinweise“ ist kein Auftrag.", "Lies jede betroffene Datei unmittelbar vor dem Editieren erneut ein.", "Wenn du mehrere Stellen in derselben Datei änderst: Erzeuge einen unified diff und nutze das apply_patch-Tool — nicht mehrere edit-Aufrufe.", "Fallback: Datei komplett neu schreiben wenn apply_patch nicht möglich.", diff --git a/tests/pure-logic.test.mjs b/tests/pure-logic.test.mjs index dd6270e..a91f15e 100644 --- a/tests/pure-logic.test.mjs +++ b/tests/pure-logic.test.mjs @@ -117,3 +117,26 @@ test("parseShipVerdict: SHIP, NO-SHIP, Markdown, unklar", () => { assert.equal(parseShipVerdict("**Urteil:** ship"), "SHIP"); assert.equal(parseShipVerdict("kein Urteil"), ""); }); + +// Judge-Prompts rufen judgeVerdictSection() auf; extractFn wertet jede Funktion einzeln aus, freie Namen landen +// im globalen Scope. +globalThis.judgeVerdictSection = extractFn("judgeVerdictSection"); +const judgePrompt = extractFn("judgePrompt"); +const judgeWithTestsPrompt = extractFn("judgeWithTestsPrompt"); +const fixPrompt = extractFn("fixPrompt"); + +test("Judge-Prompts: Urteilsregeln und Hinweise in beiden Varianten (Strata-Judge 15.10.)", () => { + for (const p of [judgePrompt(""), judgeWithTestsPrompt("1 passed", "")]) { + assert.match(p, /Urteilsregeln \(verbindlich/); + assert.match(p, /- PASS: alle Anforderungen erfüllt, Tests grün, kein Blocker und kein Major/); + assert.match(p, /„Hinweise“\. Sie ändern das Urteil nicht/); + assert.match(p, /- Hinweise \(ändern das Urteil nicht\)/); + assert.match(p, /- Urteil: PASS \| PASS WITH CONCERNS \| FAIL/); + assert.doesNotMatch(p, /Produktionsrisiken/); + } + assert.match(judgeWithTestsPrompt("3 passed", ""), /3 passed/); +}); + +test("fixPrompt: Hinweise sind kein Auftrag", () => { + assert.match(fixPrompt(""), /„Hinweise“ ist kein Auftrag/); +});