feat: Urteilsregeln für den Judge (PASS gegen TASK/SPEC, Abschnitt Hinweise)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
65555b25f1
commit
75ad2be498
4 changed files with 67 additions and 27 deletions
|
|
@ -32,11 +32,16 @@ eine andere Persona annimmt:
|
||||||
sie, führt Tests aus und erstellt Git-Commits.
|
sie, führt Tests aus und erstellt Git-Commits.
|
||||||
|
|
||||||
**Judge-Persona**: Überprüft den Code mit dem Blick eines skeptischen Senior-Entwicklers.
|
**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:
|
Prüft Korrektheit, Robustheit, Randfälle, Sicherheit und Produktionsreife. Maßstab für das Urteil
|
||||||
- `PASS` — Code ist in Ordnung
|
sind `TASK.md` und, falls vorhanden, `SPEC.md`:
|
||||||
- `PASS WITH CONCERNS` — hat Anmerkungen, die behoben werden müssen (wird wie `FAIL` behandelt,
|
- `PASS` — alle Anforderungen erfüllt, Tests grün, kein Blocker und kein Major
|
||||||
außer du verwendest `--approve-concerns`)
|
- `PASS WITH CONCERNS` — alle Anforderungen erfüllt, aber mindestens ein Major: ein konkretes Risiko im
|
||||||
- `FAIL` — enthält Blocker, die behoben werden müssen
|
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
|
Die Umschaltung zwischen den Rollen erfolgt über unterschiedliche System-Prompts, die die
|
||||||
Extension automatisch vor jeder Inference einsetzt. Es läuft kein zweiter Server.
|
Extension automatisch vor jeder Inference einsetzt. Es läuft kein zweiter Server.
|
||||||
|
|
@ -249,21 +254,22 @@ Urteil: PASS WITH CONCERNS
|
||||||
Blocker: keine
|
Blocker: keine
|
||||||
|
|
||||||
Major:
|
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:
|
Minor:
|
||||||
- Keine --version Flag
|
- Fehlermeldung nennt den Dateinamen nicht
|
||||||
- Fehlermeldung bei nicht-existenter Datei gibt keinen Exit-Code 1 zurück
|
|
||||||
|
|
||||||
Fehlende Tests:
|
Fehlende Tests:
|
||||||
- Test für leere Datei fehlt
|
- Test für leere Datei fehlt
|
||||||
- Test für Datei mit nur Leerzeichen 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
|
- Bei sehr großen Dateien (>1 GB) wird alles in den RAM geladen
|
||||||
|
- Keine --version Flag
|
||||||
|
|
||||||
Konkrete Fix-Aufträge:
|
Konkrete Fix-Aufträge:
|
||||||
1. exit(1) bei FileNotFoundError
|
1. FileNotFoundError abfangen, Meldung mit Dateiname, exit(2)
|
||||||
2. Test für leere Eingabedatei
|
2. Test für leere Eingabedatei
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
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
|
## Live-Aktivitätsstatus
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,28 @@ function coderKickoff(task: string): string {
|
||||||
].join("\n");
|
].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 {
|
function judgePrompt(extra: string): string {
|
||||||
const suffix = extra?.trim() ? "\n\nZusätzlicher Fokus des Users:\n" + extra.trim() : "";
|
const suffix = extra?.trim() ? "\n\nZusätzlicher Fokus des Users:\n" + extra.trim() : "";
|
||||||
return [
|
return [
|
||||||
|
|
@ -65,14 +87,7 @@ function judgePrompt(extra: string): string {
|
||||||
"4. Bewerte Korrektheit, Robustheit, Fehlerbehandlung, Sicherheit, Logging, Wartbarkeit und Produktionsreife.",
|
"4. Bewerte Korrektheit, Robustheit, Fehlerbehandlung, Sicherheit, Logging, Wartbarkeit und Produktionsreife.",
|
||||||
"5. Wenn etwas fehlt, sage es klar und direkt.",
|
"5. Wenn etwas fehlt, sage es klar und direkt.",
|
||||||
"",
|
"",
|
||||||
"Ausgabeformat:",
|
...judgeVerdictSection(),
|
||||||
"- Urteil: PASS | PASS WITH CONCERNS | FAIL",
|
|
||||||
"- Blocker",
|
|
||||||
"- Major",
|
|
||||||
"- Minor",
|
|
||||||
"- Fehlende Tests",
|
|
||||||
"- Produktionsrisiken",
|
|
||||||
"- Konkrete Fix-Aufträge an den Coder",
|
|
||||||
"",
|
"",
|
||||||
"Wenn du etwas behauptest, nenne die Datei, den Befehl, den Test oder den Reproduktionshinweis."
|
"Wenn du etwas behauptest, nenne die Datei, den Befehl, den Test oder den Reproduktionshinweis."
|
||||||
].join("\n") + suffix;
|
].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).",
|
"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.",
|
"4. Wenn du etwas behauptest, nenne die Datei, die Zeile oder den Reproduktionshinweis.",
|
||||||
"",
|
"",
|
||||||
"Ausgabeformat:",
|
...judgeVerdictSection(),
|
||||||
"- Urteil: PASS | PASS WITH CONCERNS | FAIL",
|
|
||||||
"- Blocker",
|
|
||||||
"- Major",
|
|
||||||
"- Minor",
|
|
||||||
"- Fehlende Tests",
|
|
||||||
"- Produktionsrisiken",
|
|
||||||
"- Konkrete Fix-Aufträge an den Coder",
|
|
||||||
].join("\n") + suffix;
|
].join("\n") + suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +123,7 @@ function fixPrompt(extra: string): string {
|
||||||
"Wechsle in den Reparaturmodus.",
|
"Wechsle in den Reparaturmodus.",
|
||||||
"Lies TASK.md als Referenz — stelle sicher, dass nach den Fixes alle Anforderungen erfüllt bleiben.",
|
"Lies TASK.md als Referenz — stelle sicher, dass nach den Fixes alle Anforderungen erfüllt bleiben.",
|
||||||
"Nutze den letzten Judge-Bericht als verbindliche Aufgabenliste.",
|
"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.",
|
"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.",
|
"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.",
|
"Fallback: Datei komplett neu schreiben wenn apply_patch nicht möglich.",
|
||||||
|
|
|
||||||
|
|
@ -117,3 +117,26 @@ test("parseShipVerdict: SHIP, NO-SHIP, Markdown, unklar", () => {
|
||||||
assert.equal(parseShipVerdict("**Urteil:** ship"), "SHIP");
|
assert.equal(parseShipVerdict("**Urteil:** ship"), "SHIP");
|
||||||
assert.equal(parseShipVerdict("kein Urteil"), "");
|
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/);
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue