feat: --interactive-Checkpoint, direktes SHIP bei PASS, default rounds 2
- /optimize --interactive pausiert nach erstem PASS; /continue setzt fort, /continue "Zusatz" hängt weiteren Auftrag an und wiederholt den Judge-Loop - Klares PASS → direkt SHIP ohne zweiten ShipIt-Inference-Call (1-3 min gespart) - PASS WITH CONCERNS → ShipIt-Runde weiterhin als finale Abwägung - Default --rounds 3→2 (~30 % schnellere Durchläufe für typische Tasks) - /continue-Command erkennt interactivePauseActive und leitet Signal weiter - Alle drei Interactive-Zustandsvariablen werden im finally-Block resettet - Dokumentation (README, BEDIENUNGSANLEITUNG, CLAUDE.md) vollständig aktualisiert Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5dee5f25e4
commit
11ac46e565
4 changed files with 248 additions and 79 deletions
|
|
@ -13,7 +13,7 @@ einfache Slash-Kommandos in der pi-Agent-Oberfläche.
|
||||||
3. [Server starten und stoppen](#3-server-starten-und-stoppen)
|
3. [Server starten und stoppen](#3-server-starten-und-stoppen)
|
||||||
4. [Neues Projekt anlegen](#4-neues-projekt-anlegen)
|
4. [Neues Projekt anlegen](#4-neues-projekt-anlegen)
|
||||||
5. [Manueller Workflow: /coder → /judge → /fix → /shipit](#5-manueller-workflow)
|
5. [Manueller Workflow: /coder → /judge → /fix → /shipit](#5-manueller-workflow)
|
||||||
6. [Automatischer Workflow: /optimize](#6-automatischer-workflow-optimize)
|
6. [Automatischer Workflow: /optimize](#6-automatischer-workflow-optimize) (inkl. [Interactive-Modus](#interactive-modus))
|
||||||
7. [Kleine Änderungen: /patch und /quick_check](#7-kleine-änderungen-patch-und-quick_check)
|
7. [Kleine Änderungen: /patch und /quick_check](#7-kleine-änderungen-patch-und-quick_check)
|
||||||
8. [Dokumentation generieren: /update_doku](#8-dokumentation-generieren-update_doku)
|
8. [Dokumentation generieren: /update_doku](#8-dokumentation-generieren-update_doku)
|
||||||
9. [Versionsverwaltung: /version](#9-versionsverwaltung-version)
|
9. [Versionsverwaltung: /version](#9-versionsverwaltung-version)
|
||||||
|
|
@ -278,14 +278,16 @@ Empfohlene Sofortmaßnahmen: keine
|
||||||
### Syntax
|
### Syntax
|
||||||
|
|
||||||
```
|
```
|
||||||
/optimize <auftrag> [--rounds N] [--with-doku] [--continue]
|
/optimize <auftrag> [--rounds N] [--with-doku] [--continue] [--interactive]
|
||||||
```
|
```
|
||||||
|
|
||||||
- `--rounds N` — maximale Anzahl Runden (Standard: 3)
|
- `--rounds N` — maximale Anzahl Runden (Standard: 2)
|
||||||
- `--with-doku` — nach SHIP automatisch `/update_doku` ausführen
|
- `--with-doku` — nach SHIP automatisch `/update_doku` ausführen
|
||||||
- `--continue` — überspringt die Implementierungsphase und startet direkt mit dem
|
- `--continue` — überspringt die Implementierungsphase und startet direkt mit dem
|
||||||
Judge→Fix-Zyklus ab dem aktuellen Code-Stand. Nützlich wenn man bereits manuell
|
Judge→Fix-Zyklus ab dem aktuellen Code-Stand. Nützlich wenn man bereits manuell
|
||||||
`/coder`, `/judge` und `/fix` durchgeführt hat und den Rest automatisieren möchte.
|
`/coder`, `/judge` und `/fix` durchgeführt hat und den Rest automatisieren möchte.
|
||||||
|
- `--interactive` — pausiert nach erstem PASS für einen menschlichen Checkpoint.
|
||||||
|
Details: siehe [Interactive-Modus](#interactive-modus) weiter unten.
|
||||||
|
|
||||||
### Beispiel: einfacher Auftrag
|
### Beispiel: einfacher Auftrag
|
||||||
|
|
||||||
|
|
@ -296,19 +298,21 @@ Empfohlene Sofortmaßnahmen: keine
|
||||||
Was im Hintergrund passiert:
|
Was im Hintergrund passiert:
|
||||||
```
|
```
|
||||||
Phase 1: Coder implementiert...
|
Phase 1: Coder implementiert...
|
||||||
Phase 2: Runde 1/3: Judge prüft...
|
Phase 2: Runde 1/2: Judge prüft...
|
||||||
→ Urteil: FAIL (2 Blocker)
|
→ Urteil: FAIL (2 Blocker)
|
||||||
Phase 3: Runde 1/3: Coder fixt...
|
Phase 3: Runde 1/2: Coder fixt...
|
||||||
Phase 4: Runde 2/3: Judge prüft...
|
Phase 4: Runde 2/2: Judge prüft...
|
||||||
→ Urteil: PASS WITH CONCERNS
|
→ Urteil: PASS WITH CONCERNS
|
||||||
✓ PASS WITH CONCERNS nach Runde 2
|
✓ PASS WITH CONCERNS nach Runde 2
|
||||||
Finale ShipIt-Prüfung...
|
Finale ShipIt-Prüfung... (nur bei PASS WITH CONCERNS)
|
||||||
→ SHIP
|
→ SHIP
|
||||||
[Dialog: Version → v0.1.0 (empfohlen)]
|
[Dialog: Version → v0.1.0 (empfohlen)]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Bei klarem `PASS` entfällt die ShipIt-Runde — es wird direkt SHIP ausgelöst.
|
||||||
|
|
||||||
Während des Ablaufs zeigt die Statuszeile immer die aktuelle Aktivität:
|
Während des Ablaufs zeigt die Statuszeile immer die aktuelle Aktivität:
|
||||||
`Coder implementiert…` → `Editiere src/main.rs…` → `Git-Commit…` → `Judge reviewt (Runde 1/3)…`
|
`Coder implementiert…` → `Editiere src/main.rs…` → `Git-Commit…` → `Judge reviewt (Runde 1/2)…`
|
||||||
|
|
||||||
### Beispiel: mehr Runden
|
### Beispiel: mehr Runden
|
||||||
|
|
||||||
|
|
@ -359,10 +363,57 @@ In diesem Fall: `/judge` manuell ausführen, Blocker lesen, mit `/fix` manuell e
|
||||||
### Max. Runden ohne PASS
|
### Max. Runden ohne PASS
|
||||||
|
|
||||||
```
|
```
|
||||||
⚠ 3 Runden durchlaufen ohne PASS. Bitte manuell prüfen.
|
⚠ 2 Runden durchlaufen ohne PASS. Bitte manuell prüfen.
|
||||||
```
|
```
|
||||||
|
|
||||||
Dann: `/judge` und `/fix` manuell für gezielte Eingriffe.
|
Dann: `/judge` und `/fix` manuell für gezielte Eingriffe.
|
||||||
|
Mit `--rounds N` kann die Grenze hochgesetzt werden, z.B. `--rounds 5` für komplexe Aufgaben.
|
||||||
|
|
||||||
|
### Interactive-Modus
|
||||||
|
|
||||||
|
Mit `--interactive` pausiert `/optimize` nach dem ersten PASS und wartet auf menschliches
|
||||||
|
Feedback — bevor das abschließende SHIP ausgelöst wird.
|
||||||
|
|
||||||
|
```
|
||||||
|
/optimize Implementiere Feature X --interactive
|
||||||
|
```
|
||||||
|
|
||||||
|
Typischer Ablauf:
|
||||||
|
```
|
||||||
|
Phase 1: Coder implementiert...
|
||||||
|
Phase 2: Judge prüft...
|
||||||
|
→ Urteil: PASS
|
||||||
|
⏸ PASS erreicht. Weitere Features? /continue "Zusatzauftrag" — oder /continue zum Shippern.
|
||||||
|
```
|
||||||
|
|
||||||
|
Jetzt hast du drei Optionen:
|
||||||
|
|
||||||
|
**Option A: Direkt shippern**
|
||||||
|
```
|
||||||
|
/continue
|
||||||
|
```
|
||||||
|
→ ShipIt wird gestartet, Version-Dialog erscheint.
|
||||||
|
|
||||||
|
**Option B: Zusatzauftrag hinzufügen**
|
||||||
|
```
|
||||||
|
/continue "Füge außerdem eine --verbose Option hinzu"
|
||||||
|
```
|
||||||
|
→ Coder implementiert den Zusatz, dann läuft der Judge-Loop erneut an.
|
||||||
|
→ Nach erneutem PASS erscheint der Checkpoint wieder — du kannst beliebig viele
|
||||||
|
Iterationen anhängen, bevor du mit `/continue` zum SHIP gehst.
|
||||||
|
|
||||||
|
**Option C: Abbrechen**
|
||||||
|
```
|
||||||
|
/cancel
|
||||||
|
```
|
||||||
|
→ Loop wird abgebrochen, kein SHIP.
|
||||||
|
|
||||||
|
**Timeout:** Wenn du 30 Minuten lang nichts eingibst, bricht `/optimize` automatisch ab.
|
||||||
|
|
||||||
|
**Wann ist `--interactive` sinnvoll?**
|
||||||
|
- Wenn der Auftrag aus mehreren voneinander abhängigen Features besteht
|
||||||
|
- Wenn du nach jeder fertigen Stufe entscheiden möchtest, ob du weitermachst
|
||||||
|
- Wenn du sicherstellen willst, dass nichts unbeabsichtigt committed wird
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -678,6 +729,28 @@ Die Checkboxen werden automatisch abgehakt:
|
||||||
/optimize Schreibe einen vollständigen Markdown-Parser mit AST in Python --rounds 5
|
/optimize Schreibe einen vollständigen Markdown-Parser mit AST in Python --rounds 5
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Schrittweise Features hinzufügen mit --interactive
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Erst Grundgerüst implementieren und PASS abwarten:
|
||||||
|
/optimize Schreibe ein CLI-Tool 'filewatch' das Dateiänderungen überwacht --interactive
|
||||||
|
|
||||||
|
# Nach PASS erscheint: ⏸ PASS – warte auf /continue…
|
||||||
|
|
||||||
|
# Option A: Genug, direkt shippern:
|
||||||
|
/continue
|
||||||
|
|
||||||
|
# Option B: Weiteres Feature anhängen:
|
||||||
|
/continue "Füge außerdem einen --filter GLOB-Parameter hinzu"
|
||||||
|
# → Coder implementiert, Judge prüft erneut, PASS → Checkpoint wieder aktiv
|
||||||
|
|
||||||
|
# Nochmal erweitern:
|
||||||
|
/continue "Füge --output-log DATEI hinzu um Änderungen zu protokollieren"
|
||||||
|
|
||||||
|
# Fertig → shippern:
|
||||||
|
/continue
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Fehlermeldungen und Lösungen
|
## 12. Fehlermeldungen und Lösungen
|
||||||
|
|
@ -750,7 +823,7 @@ bereit, das GNU `patch -p1` mit Fuzzy-Matching nutzt.
|
||||||
Lies die Datei neu ein und wende die Änderungen als unified diff mit apply_patch an.
|
Lies die Datei neu ein und wende die Änderungen als unified diff mit apply_patch an.
|
||||||
```
|
```
|
||||||
|
|
||||||
### "Drei Runden ohne PASS" / Loop-Erkennung schlägt an
|
### "N Runden ohne PASS" / Loop-Erkennung schlägt an
|
||||||
|
|
||||||
```
|
```
|
||||||
⚠ Derselbe Blocker tritt erneut auf – Schleife abgebrochen.
|
⚠ Derselbe Blocker tritt erneut auf – Schleife abgebrochen.
|
||||||
|
|
@ -767,6 +840,7 @@ Dann den Blocker analysieren und entweder:
|
||||||
- `/fix Ignoriere Blocker X, das ist nicht Teil dieser Aufgabe`
|
- `/fix Ignoriere Blocker X, das ist nicht Teil dieser Aufgabe`
|
||||||
- Den Code selbst anpassen und dann `/fix` aufrufen
|
- Den Code selbst anpassen und dann `/fix` aufrufen
|
||||||
- Die Aufgabe in TASK.md präzisieren
|
- Die Aufgabe in TASK.md präzisieren
|
||||||
|
- Bei komplexen Aufgaben mit mehr Runden wiederholen: `/optimize --continue --rounds 5`
|
||||||
|
|
||||||
### Server läuft, aber pi wechselt nicht das Modell
|
### Server läuft, aber pi wechselt nicht das Modell
|
||||||
|
|
||||||
|
|
|
||||||
10
CLAUDE.md
10
CLAUDE.md
|
|
@ -41,9 +41,12 @@ Beide nutzen dasselbe GGUF (`Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.g
|
||||||
**Zentraler Ablauf in `/optimize`:**
|
**Zentraler Ablauf in `/optimize`:**
|
||||||
1. `writeTaskMd()` → TASK.md anlegen
|
1. `writeTaskMd()` → TASK.md anlegen
|
||||||
2. Coder: `coderKickoff()` → implementiert + committet
|
2. Coder: `coderKickoff()` → implementiert + committet
|
||||||
3. Loop (max. N Runden): Judge → `parseVerdict()` → PASS? → ShipIt. FAIL? → `parseBlockers()` → Fix → nächste Runde
|
3. Äußere `while(keepGoing)`-Schleife (für `--interactive`-Zusatzaufträge)
|
||||||
4. Loop-Erkennung: gleicher Blocker zweimal → Abbruch (`finalNotify()`)
|
4. Loop (max. N Runden, Standard 2): Judge → `parseVerdict()` → PASS? → break. FAIL? → `parseBlockers()` → Fix → nächste Runde
|
||||||
5. Optional: `runUpdateDoku()` bei `--with-doku`
|
5. Bei PASS + `--interactive`: Polling auf `interactiveContinueRequested`. Kein Zusatzauftrag → ShipIt. Zusatzauftrag → `coderKickoff()` → `keepGoing = true`
|
||||||
|
6. SHIP-Schritt: klares `PASS` → direkt SHIP (kein ShipIt-Call). `PASS WITH CONCERNS` → `shipitPrompt()` → SHIP/NO-SHIP
|
||||||
|
7. Loop-Erkennung: gleicher Blocker zweimal → Abbruch (`finalNotify()`)
|
||||||
|
8. 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.
|
**`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.
|
||||||
|
|
||||||
|
|
@ -60,6 +63,7 @@ Kritische Felder bei llama-cpp-Providern: `contextWindow` muss mit dem `-c`-Para
|
||||||
## Wichtige Invarianten
|
## Wichtige Invarianten
|
||||||
|
|
||||||
- **`cancelRequested`** ist eine modulare Variable — sie wird von `/cancel` gesetzt und nach jedem Loop-Schritt in `/optimize` geprüft und zurückgesetzt.
|
- **`cancelRequested`** ist eine modulare Variable — sie wird von `/cancel` gesetzt und nach jedem Loop-Schritt in `/optimize` geprüft und zurückgesetzt.
|
||||||
|
- **`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".
|
- **`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).
|
- **`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.
|
- Beide Start-Skripte warten bis zu 90×2 s auf HTTP-Erreichbarkeit und führen dann einen Smoke-Test-Completion durch.
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,10 @@ Nutzer gibt Auftrag
|
||||||
│
|
│
|
||||||
PASS? ▼
|
PASS? ▼
|
||||||
/shipit → qwen3.5-judge (:8002) → Finale Freigabe: SHIP / NO-SHIP
|
/shipit → qwen3.5-judge (:8002) → Finale Freigabe: SHIP / NO-SHIP
|
||||||
|
(nur bei "PASS WITH CONCERNS" — klares PASS → direkt SHIP)
|
||||||
|
|
||||||
/optimize = Coder→Judge→Fix-Schleife automatisch (bis PASS oder max. N Runden)
|
/optimize = Coder→Judge→Fix-Schleife automatisch (bis PASS oder max. N Runden)
|
||||||
|
--interactive: pausiert nach PASS für menschlichen Checkpoint + optionale Zusatzaufträge
|
||||||
```
|
```
|
||||||
|
|
||||||
Beide Modelle laufen als **separate llama.cpp-Docker-Container** und sprechen eine
|
Beide Modelle laufen als **separate llama.cpp-Docker-Container** und sprechen eine
|
||||||
|
|
@ -283,7 +285,7 @@ wenn pi agent Folgeanfragen schnell hintereinander schickt.
|
||||||
| `/judge [fokus]` | Judge | Code-Review gegen TASK.md + letzten Commit |
|
| `/judge [fokus]` | Judge | Code-Review gegen TASK.md + letzten Commit |
|
||||||
| `/fix [hinweis]` | Coder | Judge-Kritik beheben, committen |
|
| `/fix [hinweis]` | Coder | Judge-Kritik beheben, committen |
|
||||||
| `/shipit` | Judge | Finale Freigabeprüfung |
|
| `/shipit` | Judge | Finale Freigabeprüfung |
|
||||||
| `/optimize <auftrag> [--rounds N] [--with-doku] [--continue]` | beide | Vollautomatische Schleife bis PASS |
|
| `/optimize <auftrag> [--rounds N] [--with-doku] [--continue] [--interactive]` | beide | Vollautomatische Schleife bis PASS (Standard: 2 Runden) |
|
||||||
| `/optimize ... [--test-cmd "cmd"] [--test-timeout N]` | beide | Externe Test-Suite im Loop ausführen |
|
| `/optimize ... [--test-cmd "cmd"] [--test-timeout N]` | beide | Externe Test-Suite im Loop ausführen |
|
||||||
| `/patch <änderung>` | Coder | Gezielte Minimaländerung ohne Review |
|
| `/patch <änderung>` | Coder | Gezielte Minimaländerung ohne Review |
|
||||||
| `/quick_check [was]` | Judge | Schnelle Prüfung der letzten Änderung |
|
| `/quick_check [was]` | Judge | Schnelle Prüfung der letzten Änderung |
|
||||||
|
|
@ -307,8 +309,9 @@ Während der Ausführung zeigt pi_coder in der Statuszeile, was gerade passiert:
|
||||||
| Coder implementiert | `Coder implementiert…` |
|
| Coder implementiert | `Coder implementiert…` |
|
||||||
| edit-Tool aktiv | `Editiere src/main.py…` |
|
| edit-Tool aktiv | `Editiere src/main.py…` |
|
||||||
| git commit | `Git-Commit…` |
|
| git commit | `Git-Commit…` |
|
||||||
| Judge reviewt (Runde 2/3) | `Judge reviewt (Runde 2/3)…` |
|
| Judge reviewt (Runde 2/2) | `Judge reviewt (Runde 2/2)…` |
|
||||||
| Tests laufen | `Tests laufen…` |
|
| Tests laufen | `Tests laufen…` |
|
||||||
| Fix-Phase | `Coder fixt Blocker…` |
|
| Fix-Phase | `Coder fixt Blocker…` |
|
||||||
|
| Interactive-Pause (--interactive) | `⏸ PASS – warte auf /continue…` |
|
||||||
|
|
||||||
So ist jederzeit erkennbar, in welcher Phase sich der automatische Loop befindet.
|
So ist jederzeit erkennbar, in welcher Phase sich der automatische Loop befindet.
|
||||||
|
|
|
||||||
|
|
@ -827,6 +827,9 @@ function finalNotify(
|
||||||
// ── Extension ────────────────────────────────────────────────────────────────
|
// ── Extension ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
let cancelRequested = false;
|
let cancelRequested = false;
|
||||||
|
let interactivePauseActive = false;
|
||||||
|
let interactiveContinueRequested = false;
|
||||||
|
let interactivePauseTask = "";
|
||||||
let currentActivity = ""; // Working-Message für den aktuellen Command-Kontext
|
let currentActivity = ""; // Working-Message für den aktuellen Command-Kontext
|
||||||
|
|
||||||
// Erzeugt eine knappe Statuszeile aus Tool-Name und Argumenten.
|
// Erzeugt eine knappe Statuszeile aus Tool-Name und Argumenten.
|
||||||
|
|
@ -1000,12 +1003,13 @@ export default function (pi: ExtensionAPI) {
|
||||||
// ── Automatische Optimierungsschleife ────────────────────────────────────
|
// ── Automatische Optimierungsschleife ────────────────────────────────────
|
||||||
|
|
||||||
pi.registerCommand("optimize", {
|
pi.registerCommand("optimize", {
|
||||||
description: "Coder→Judge→Fix-Schleife bis PASS. Tests werden automatisch erkannt und parallel ausgeführt. /optimize <auftrag> [--rounds N] [--with-doku] [--continue] [--test-cmd \"override\"] [--test-timeout N]",
|
description: "Coder→Judge→Fix-Schleife bis PASS (default 2 Runden). Klares PASS → direkt SHIP; PASS WITH CONCERNS → ShipIt-Runde. --interactive pausiert nach PASS für Zusatzaufträge via /continue. /optimize <auftrag> [--rounds N] [--with-doku] [--continue] [--interactive] [--test-cmd \"override\"] [--test-timeout N]",
|
||||||
handler: async function (args: string, ctx: ExtensionCommandContext) {
|
handler: async function (args: string, ctx: ExtensionCommandContext) {
|
||||||
const roundsMatch = (args || "").match(/--rounds\s+(\d+)/);
|
const roundsMatch = (args || "").match(/--rounds\s+(\d+)/);
|
||||||
const maxRounds = roundsMatch ? Math.max(1, parseInt(roundsMatch[1], 10)) : 3;
|
const maxRounds = roundsMatch ? Math.max(1, parseInt(roundsMatch[1], 10)) : 2;
|
||||||
const withDoku = /--with-doku/.test(args || "");
|
const withDoku = /--with-doku/.test(args || "");
|
||||||
const continueMode = /--continue/.test(args || "");
|
const continueMode = /--continue/.test(args || "");
|
||||||
|
const interactive = /--interactive/.test(args || "");
|
||||||
const testCmdMatch = (args || "").match(/--test-cmd\s+"([^"]+)"|--test-cmd\s+'([^']+)'|--test-cmd\s+(\S+)/);
|
const testCmdMatch = (args || "").match(/--test-cmd\s+"([^"]+)"|--test-cmd\s+'([^']+)'|--test-cmd\s+(\S+)/);
|
||||||
const testCmd: string | null = testCmdMatch ? (testCmdMatch[1] ?? testCmdMatch[2] ?? testCmdMatch[3]) : null;
|
const testCmd: string | null = testCmdMatch ? (testCmdMatch[1] ?? testCmdMatch[2] ?? testCmdMatch[3]) : null;
|
||||||
const testTimeoutMatch = (args || "").match(/--test-timeout\s+(\d+)/);
|
const testTimeoutMatch = (args || "").match(/--test-timeout\s+(\d+)/);
|
||||||
|
|
@ -1015,6 +1019,7 @@ export default function (pi: ExtensionAPI) {
|
||||||
.replace(/--test-timeout\s+\d+/, "")
|
.replace(/--test-timeout\s+\d+/, "")
|
||||||
.replace(/--with-doku/, "")
|
.replace(/--with-doku/, "")
|
||||||
.replace(/--continue/, "")
|
.replace(/--continue/, "")
|
||||||
|
.replace(/--interactive/, "")
|
||||||
.replace(/--test-cmd\s+"[^"]*"/, "")
|
.replace(/--test-cmd\s+"[^"]*"/, "")
|
||||||
.replace(/--test-cmd\s+\S+/, "")
|
.replace(/--test-cmd\s+\S+/, "")
|
||||||
.trim();
|
.trim();
|
||||||
|
|
@ -1085,6 +1090,13 @@ export default function (pi: ExtensionAPI) {
|
||||||
|
|
||||||
let lastBlockers = "";
|
let lastBlockers = "";
|
||||||
let verdict = "";
|
let verdict = "";
|
||||||
|
let keepGoing = true;
|
||||||
|
|
||||||
|
// Äußere Schleife für --interactive: nach PASS pausieren, Zusatzaufträge ermöglichen.
|
||||||
|
while (keepGoing) {
|
||||||
|
keepGoing = false;
|
||||||
|
verdict = "";
|
||||||
|
lastBlockers = "";
|
||||||
|
|
||||||
// Schleife: Judge → (PASS? fertig : Fix → nächste Runde)
|
// Schleife: Judge → (PASS? fertig : Fix → nächste Runde)
|
||||||
for (let round = 1; round <= maxRounds; round++) {
|
for (let round = 1; round <= maxRounds; round++) {
|
||||||
|
|
@ -1115,7 +1127,8 @@ export default function (pi: ExtensionAPI) {
|
||||||
|
|
||||||
if (verdict === "PASS" || verdict === "PASS WITH CONCERNS") {
|
if (verdict === "PASS" || verdict === "PASS WITH CONCERNS") {
|
||||||
await tickTaskMdStatus(pi, ctx, "Review bestanden (PASS)");
|
await tickTaskMdStatus(pi, ctx, "Review bestanden (PASS)");
|
||||||
ctx.ui.setStatus("optimize", `${"●".repeat(round)} ✓ ${verdict} nach Runde ${round}/${maxRounds} — ShipIt…`);
|
const nextStep = interactive ? "warte auf /continue…" : "ShipIt…";
|
||||||
|
ctx.ui.setStatus("optimize", `${"●".repeat(round)} ✓ ${verdict} nach Runde ${round}/${maxRounds} — ${nextStep}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1152,9 +1165,69 @@ export default function (pi: ExtensionAPI) {
|
||||||
if (cancelRequested) { finalNotify(ctx, "⛔ Abgebrochen", `Nach Fix Runde ${round}`); return; }
|
if (cancelRequested) { finalNotify(ctx, "⛔ Abgebrochen", `Nach Fix Runde ${round}`); return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finale ShipIt-Prüfung nur bei PASS
|
// Interactive-Modus: nach PASS pausieren und auf /continue warten (max 30 min).
|
||||||
if (verdict === "PASS" || verdict === "PASS WITH CONCERNS") {
|
// /continue ohne Args → direkt ShipIt. /continue "Zusatz" → Coder implementiert, Loop nochmal.
|
||||||
ctx.ui.setStatus("optimize", `${"●".repeat(maxRounds)}◉ ShipIt — SHIP oder NO-SHIP?…`);
|
if (interactive && (verdict === "PASS" || verdict === "PASS WITH CONCERNS")) {
|
||||||
|
interactivePauseActive = true;
|
||||||
|
interactiveContinueRequested = false;
|
||||||
|
interactivePauseTask = "";
|
||||||
|
|
||||||
|
ctx.ui.setStatus("optimize", `⏸ ${verdict} – warte auf /continue…`);
|
||||||
|
ctx.ui.notify(
|
||||||
|
`✅ ${verdict} erreicht. Weitere Features? /continue "Zusatzauftrag" — oder /continue zum Shippern.`,
|
||||||
|
"info"
|
||||||
|
);
|
||||||
|
|
||||||
|
const waitStart = Date.now();
|
||||||
|
while (!interactiveContinueRequested && !cancelRequested) {
|
||||||
|
if (Date.now() - waitStart > 30 * 60 * 1000) {
|
||||||
|
interactivePauseActive = false;
|
||||||
|
finalNotify(ctx, "⚠ Timeout", "30 min ohne /continue — abgebrochen");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
}
|
||||||
|
interactivePauseActive = false;
|
||||||
|
|
||||||
|
if (cancelRequested) { finalNotify(ctx, "⛔ Abgebrochen", "Im Interactive-Modus"); return; }
|
||||||
|
|
||||||
|
if (interactivePauseTask) {
|
||||||
|
// Zusatzauftrag: Coder implementiert, dann Judge-Loop erneut
|
||||||
|
const addPreview = interactivePauseTask.length > 50
|
||||||
|
? interactivePauseTask.slice(0, 47) + "…"
|
||||||
|
: interactivePauseTask;
|
||||||
|
ctx.ui.setStatus("optimize", `◉ Coder implementiert Zusatzauftrag: ${addPreview}`);
|
||||||
|
await writeTaskMd(pi, ctx, interactivePauseTask);
|
||||||
|
if (!await switchModel(pi, ctx, "llama-cpp-coder", "qwen3.5-coder")) {
|
||||||
|
finalNotify(ctx, "⛔ Modell-Fehler", "Coder-Modell nicht verfügbar");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentActivity = "Coder implementiert Zusatzauftrag…";
|
||||||
|
await sendAndWait(pi, ctx, coderKickoff(interactivePauseTask));
|
||||||
|
await tickTaskMdStatus(pi, ctx, "Implementierung");
|
||||||
|
if (cancelRequested) { finalNotify(ctx, "⛔ Abgebrochen", "Nach Zusatz-Implementierung"); return; }
|
||||||
|
keepGoing = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// /continue ohne Args → direkt zu ShipIt (verdict bleibt PASS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finaler SHIP-Schritt: klares PASS → direkt SHIP ohne zweiten Inference-Aufruf.
|
||||||
|
// "PASS WITH CONCERNS" → ShipIt-Runde als finale Abwägung.
|
||||||
|
if (verdict === "PASS") {
|
||||||
|
ctx.ui.setStatus("optimize", "🚀 SHIP – produktionsreif");
|
||||||
|
await autoCommitIfDirty(pi, ctx);
|
||||||
|
notifyShipSuccess(ctx);
|
||||||
|
finalNotify(ctx, "🚀 SHIP", "Programm ist produktionsreif");
|
||||||
|
await runVersionBump(pi, ctx);
|
||||||
|
if (withDoku) {
|
||||||
|
await runUpdateDoku(pi, ctx);
|
||||||
|
} else {
|
||||||
|
ctx.ui.notify("Nächster Schritt: /update_doku für Code-Kommentare, README.md und BEDIENUNGSANLEITUNG.md", "info");
|
||||||
|
}
|
||||||
|
} else if (verdict === "PASS WITH CONCERNS") {
|
||||||
|
ctx.ui.setStatus("optimize", `${"●".repeat(maxRounds)}◉ ShipIt — PASS WITH CONCERNS, finale Freigabe?…`);
|
||||||
if (!await switchModel(pi, ctx, "llama-cpp-judge", "qwen3.5-judge")) {
|
if (!await switchModel(pi, ctx, "llama-cpp-judge", "qwen3.5-judge")) {
|
||||||
finalNotify(ctx, "⛔ Modell-Fehler", "Judge-Modell (llama-cpp-judge) nicht verfügbar");
|
finalNotify(ctx, "⛔ Modell-Fehler", "Judge-Modell (llama-cpp-judge) nicht verfügbar");
|
||||||
return;
|
return;
|
||||||
|
|
@ -1187,8 +1260,11 @@ export default function (pi: ExtensionAPI) {
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
finalNotify(ctx, "⛔ Fehler", String(e?.message ?? e));
|
finalNotify(ctx, "⛔ Fehler", String(e?.message ?? e));
|
||||||
} finally {
|
} finally {
|
||||||
// Sicherstellen dass cancelRequested nie in einen späteren /optimize-Aufruf leckt
|
// Sicherstellen dass keine Zustandsvariable in späteren /optimize-Aufruf leckt
|
||||||
cancelRequested = false;
|
cancelRequested = false;
|
||||||
|
interactivePauseActive = false;
|
||||||
|
interactiveContinueRequested = false;
|
||||||
|
interactivePauseTask = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1352,8 +1428,20 @@ export default function (pi: ExtensionAPI) {
|
||||||
});
|
});
|
||||||
|
|
||||||
pi.registerCommand("continue", {
|
pi.registerCommand("continue", {
|
||||||
description: "Nimmt unterbrochenen Prozess wieder auf — liest TASK.md, PLAN.md, git log und entscheidet den nächsten Schritt.",
|
description: "Im --interactive-Modus: bestätigt PASS und geht zu ShipIt — oder /continue \"Zusatz\" für weiteren Auftrag. Sonst: nimmt unterbrochenen Prozess wieder auf.",
|
||||||
handler: async function (_args: string, ctx: ExtensionCommandContext) {
|
handler: async function (args: string, ctx: ExtensionCommandContext) {
|
||||||
|
// Interactive-Pause-Handler: Signal an laufenden /optimize-Loop
|
||||||
|
if (interactivePauseActive) {
|
||||||
|
interactivePauseTask = (args || "").trim();
|
||||||
|
interactiveContinueRequested = true;
|
||||||
|
const msg = interactivePauseTask
|
||||||
|
? `Zusatzauftrag eingetragen: "${interactivePauseTask}" — Coder startet`
|
||||||
|
: "Fortfahren — ShipIt wird gestartet";
|
||||||
|
ctx.ui.notify(msg, "info");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard-Verhalten: unterbrochenen Prozess wieder aufnehmen
|
||||||
if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-coder")) {
|
if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-coder")) {
|
||||||
ctx.ui.notify("Coder-Server nicht bereit (Port 8001) — start-coder.sh ausführen", "error");
|
ctx.ui.notify("Coder-Server nicht bereit (Port 8001) — start-coder.sh ausführen", "error");
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue