Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/solve_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -1953,6 +1953,7 @@ def run_openrouter_direct_worker(
0 — Alle gefundenen Patches erfolgreich angewendet.
1 — Patches gefunden, aber alle fehlgeschlagen oder API-Fehler.
2 — Modell hat Prosa ohne auswertbare Diffs zurueckgegeben.
5 — Patch-Anwendung hat Reject-Artefakte erzeugt; harter Fehler.
6 — Nur ein Teil der Patches wurde angewendet; harter Fehler.

Args:
Expand Down
11 changes: 11 additions & 0 deletions tests/test_worker_adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,17 @@ def test_partial_patch_failure_with_changes_stops(self):
True,
)

def test_patch_validation_failed_with_changes_stops(self):
"""Reject artifacts are a hard stop, even with file changes."""
from workers.base import PATCH_VALIDATION_FAILED_RETURN_CODE
self._assert_consistent(
PATCH_VALIDATION_FAILED_RETURN_CODE,
" M scripts/solve_issues.py\n",
"patch_validation_failed",
False,
True,
)

def test_aider_side_effects_only_stops(self):
"""Nur Aider-Nebenwirkungen ohne Änderungen → stoppt."""
self._assert_consistent(1, "?? .aider.chat.history.md\n",
Expand Down
13 changes: 13 additions & 0 deletions tests/test_worker_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
run_worker_subprocess,
)
from workers.base import (
PATCH_VALIDATION_FAILED_RETURN_CODE,
PARTIAL_PATCH_FAILURE_RETURN_CODE,
WorkerOutcome,
WorkerRunResult,
Expand Down Expand Up @@ -113,6 +114,18 @@ def test_partial_patch_failure_with_changes_stops(self):
self.assertFalse(outcome.should_continue)
self.assertTrue(outcome.has_changes)

def test_patch_validation_failed_with_changes_stops(self):
outcome = classify_worker_outcome(
self._make_result(
PATCH_VALIDATION_FAILED_RETURN_CODE,
"VALIDATION-FAILED: Reject-Artifakte wurden erkannt",
),
" M scripts/solve_issues.py\n",
)
self.assertEqual(outcome.reason, "patch_validation_failed")
self.assertFalse(outcome.should_continue)
self.assertTrue(outcome.has_changes)

def test_nonzero_without_changes_stops(self):
outcome = classify_worker_outcome(self._make_result(1), "")
self.assertEqual(outcome.reason, "nonzero_without_changes")
Expand Down
6 changes: 4 additions & 2 deletions workers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
no_changes → Worker erfolgreich, keine Änderungen
nonzero_with_changes → Worker mit Fehlercode, aber Änderungen vorhanden
nonzero_without_changes → Worker mit Fehlercode, keine Änderungen
patch_validation_failed → Patch-Anwendung erzeugte Reject-Artefakte
partial_patch_failure → Worker hat nur einen Teil der Patches angewendet
rate_limit_deferred → Codex Rate-Limit, kein sofortiger Retry
failed_worker → Worker nicht gefunden oder nicht startbar
Expand All @@ -28,8 +29,9 @@
from typing import Any


# Return code for workers that applied only part of a generated patch set.
# This must be treated as a hard failure even when the working tree changed.
# Return codes for patch-applying workers that must hard-stop even when
# the working tree changed.
PATCH_VALIDATION_FAILED_RETURN_CODE = 5
PARTIAL_PATCH_FAILURE_RETURN_CODE = 6


Expand Down
3 changes: 3 additions & 0 deletions workers/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from typing import Any, Callable

from workers.base import (
PATCH_VALIDATION_FAILED_RETURN_CODE,
PARTIAL_PATCH_FAILURE_RETURN_CODE,
WorkerOutcome,
WorkerRunResult,
Expand Down Expand Up @@ -309,6 +310,8 @@ def classify_worker_outcome(

if result.returncode == PARTIAL_PATCH_FAILURE_RETURN_CODE:
return WorkerOutcome(False, has_changes, "partial_patch_failure")
if result.returncode == PATCH_VALIDATION_FAILED_RETURN_CODE:
return WorkerOutcome(False, has_changes, "patch_validation_failed")
if result.returncode == 0 and has_changes:
return WorkerOutcome(True, True, "changed")
if result.returncode == 0:
Expand Down
10 changes: 7 additions & 3 deletions workers/openrouter_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
import requests
import json

from workers.base import PARTIAL_PATCH_FAILURE_RETURN_CODE
from workers.base import (
PATCH_VALIDATION_FAILED_RETURN_CODE,
PARTIAL_PATCH_FAILURE_RETURN_CODE,
)


# JSON-Schema für strukturierten Output (OpenRouter response_format).
Expand Down Expand Up @@ -804,7 +807,8 @@ def run_direct(
oder API-Fehler.
2 — Modell hat Prosa ohne auswertbare Diffs zurückgegeben.
3 — Request-Timeout überschritten.
5 — Patch-Anwendung hat Reject-Artifakte (.orig/.rej) erzeugt.
5 — Patch-Anwendung hat Reject-Artifakte (.orig/.rej) erzeugt;
der Lauf ist nicht lieferbar und muss als Fehler gelten.
6 — Nur ein Teil der Patches wurde angewendet; der Lauf ist
nicht lieferbar und muss als Fehler gelten.

Expand Down Expand Up @@ -927,7 +931,7 @@ def run_direct(
)

if has_rejects:
returncode = 5
returncode = PATCH_VALIDATION_FAILED_RETURN_CODE
log_lines.append(
f"[openrouter_direct] VALIDATION-FAILED: Reject-Artifakte wurden erkannt "
f"und bereinigt. Der gesamte Lauf gilt als fehlgeschlagen."
Expand Down
Loading