Make agent validation self-correcting
This commit is contained in:
@@ -43,6 +43,7 @@ class Settings:
|
||||
poll_seconds: int
|
||||
max_changed_files: int
|
||||
max_changed_lines: int
|
||||
max_agent_attempts: int
|
||||
stale_claim_minutes: int
|
||||
dry_run: bool
|
||||
|
||||
@@ -75,7 +76,7 @@ class Settings:
|
||||
test_commands=_commands(
|
||||
os.getenv(
|
||||
"TEST_COMMANDS",
|
||||
"composer install --no-interaction --prefer-dist;;php artisan migrate:fresh --force;;php artisan test",
|
||||
"composer install --no-interaction --prefer-dist;;npm ci;;npm run build;;php artisan migrate:fresh --force;;php artisan test",
|
||||
)
|
||||
),
|
||||
test_database_host=os.getenv("TEST_DB_HOST", "host.docker.internal"),
|
||||
@@ -88,6 +89,7 @@ class Settings:
|
||||
poll_seconds=int(os.getenv("POLL_SECONDS", "60")),
|
||||
max_changed_files=int(os.getenv("MAX_CHANGED_FILES", "12")),
|
||||
max_changed_lines=int(os.getenv("MAX_CHANGED_LINES", "800")),
|
||||
max_agent_attempts=int(os.getenv("MAX_AGENT_ATTEMPTS", "2")),
|
||||
stale_claim_minutes=int(os.getenv("STALE_CLAIM_MINUTES", "90")),
|
||||
dry_run=mode == "dry-run",
|
||||
)
|
||||
@@ -103,3 +105,5 @@ class Settings:
|
||||
raise ValueError("FAILURE_DB_PASSWORD is required")
|
||||
if not self.test_database_password:
|
||||
raise ValueError("TEST_DB_PASSWORD is required")
|
||||
if not 1 <= self.max_agent_attempts <= 3:
|
||||
raise ValueError("MAX_AGENT_ATTEMPTS must be between 1 and 3")
|
||||
|
||||
@@ -71,3 +71,17 @@ Generated SQL, if relevant:
|
||||
|
||||
Run focused tests while working. Leave the repository with the fix and regression test applied.
|
||||
"""
|
||||
|
||||
|
||||
def build_retry_task(exception: Exception) -> str:
|
||||
failure = redact(str(exception))[-6_000:]
|
||||
|
||||
return f"""The previous implementation failed isolated validation.
|
||||
|
||||
Correct the existing changes using this test output:
|
||||
|
||||
{failure}
|
||||
|
||||
Keep the regression test meaningful. Do not remove or weaken tests, safety checks,
|
||||
authentication, authorization, SQL validation, or tenant isolation. Do not commit or push.
|
||||
"""
|
||||
|
||||
@@ -12,7 +12,7 @@ from .git import GitWorkspace
|
||||
from .gitea import GiteaClient
|
||||
from .models import FailureReport
|
||||
from .policy import evaluate_changes
|
||||
from .prompt import build_task
|
||||
from .prompt import build_retry_task, build_task
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@@ -43,15 +43,29 @@ class AutomationWorker:
|
||||
try:
|
||||
workspace.prepare()
|
||||
task = build_task(report)
|
||||
metadata["agent_output"] = self.agent.run(workspace.path, task)
|
||||
metadata["agent_output"] = []
|
||||
for attempt in range(1, self.settings.max_agent_attempts + 1):
|
||||
metadata["agent_output"].append(self.agent.run(workspace.path, task))
|
||||
summary = workspace.summary()
|
||||
metadata["changes"] = asdict(summary)
|
||||
policy = evaluate_changes(summary, self.settings, workspace.path)
|
||||
if not policy.allowed:
|
||||
raise RuntimeError(
|
||||
"Policy rejected changes: " + "; ".join(policy.errors)
|
||||
)
|
||||
try:
|
||||
metadata["tests"] = self._run_tests(workspace)
|
||||
break
|
||||
except RuntimeError as exception:
|
||||
if attempt >= self.settings.max_agent_attempts:
|
||||
raise
|
||||
LOG.warning(
|
||||
"Tests failed for report %s on attempt %s; requesting correction",
|
||||
report.id,
|
||||
attempt,
|
||||
)
|
||||
task = build_retry_task(exception)
|
||||
|
||||
summary = workspace.summary()
|
||||
metadata["changes"] = asdict(summary)
|
||||
policy = evaluate_changes(summary, self.settings, workspace.path)
|
||||
if not policy.allowed:
|
||||
raise RuntimeError("Policy rejected changes: " + "; ".join(policy.errors))
|
||||
|
||||
metadata["tests"] = self._run_tests(workspace)
|
||||
summary = workspace.summary()
|
||||
metadata["changes"] = asdict(summary)
|
||||
policy = evaluate_changes(summary, self.settings, workspace.path)
|
||||
@@ -101,6 +115,9 @@ class AutomationWorker:
|
||||
results = []
|
||||
test_environment = {
|
||||
"AGENT_TEST_DB_ENABLED": "true",
|
||||
"APP_ENV": "testing",
|
||||
"APP_KEY": "base64:MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=",
|
||||
"AI_MISTRAL_API_KEY": "automation-test-key",
|
||||
"TEST_DB_HOST": self.settings.test_database_host,
|
||||
"TEST_DB_PORT": str(self.settings.test_database_port),
|
||||
"TEST_DB_NAME": self.settings.test_database_name,
|
||||
|
||||
Reference in New Issue
Block a user