feat: retry failed agent validations
This commit is contained in:
@@ -30,6 +30,7 @@ def settings(tmp_path: Path) -> Settings:
|
||||
agent_wall_time_seconds=1200,
|
||||
agent_step_limit=40,
|
||||
agent_cost_limit=5.0,
|
||||
max_agent_attempts=1,
|
||||
agent_user="coder",
|
||||
setup_commands=("composer install",),
|
||||
test_commands=("php artisan test",),
|
||||
|
||||
@@ -20,6 +20,21 @@ def test_task_uses_issue_text_not_github_parser() -> None:
|
||||
assert issue.body in task
|
||||
|
||||
|
||||
def test_task_includes_validation_feedback_for_repair_attempt() -> None:
|
||||
issue = Issue(
|
||||
number=43,
|
||||
title="Broken query",
|
||||
body="Original report",
|
||||
html_url="https://gitea.example.test/owner/lai/issues/43",
|
||||
labels=(),
|
||||
)
|
||||
|
||||
task = MiniSWEAgentRunner._task(issue, "PHP parse error on line 3")
|
||||
|
||||
assert "previous attempt failed deterministic validation" in task
|
||||
assert "PHP parse error on line 3" in task
|
||||
|
||||
|
||||
def test_system_prompt_requires_precise_diff_hygiene() -> None:
|
||||
assert "Never create backup files" in _SYSTEM_TEMPLATE
|
||||
assert "failure-report transport code" in _SYSTEM_TEMPLATE
|
||||
|
||||
@@ -30,6 +30,7 @@ def test_settings_load_issue_workflow_defaults(
|
||||
assert settings.queued_label == "ai:queued"
|
||||
assert settings.running_label == "ai:running"
|
||||
assert settings.agent_model == "mistral/devstral-latest"
|
||||
assert settings.max_agent_attempts == 3
|
||||
assert settings.test_commands == ("npm run build", "php artisan test")
|
||||
assert settings.test_environment["DB_DATABASE"] == "lai_agent_test"
|
||||
assert settings.test_environment["ERP_DATABASE"] == "customer_agent_test"
|
||||
|
||||
@@ -175,6 +175,50 @@ def test_agent_failure_details_identify_step_limit(settings) -> None:
|
||||
assert "issue-43.traj.json" in details
|
||||
|
||||
|
||||
@patch("lai_automation.worker.GitWorkspace")
|
||||
def test_failed_validation_is_given_to_repair_attempt(
|
||||
GitWorkspace,
|
||||
settings,
|
||||
) -> None:
|
||||
settings = settings.__class__(
|
||||
**{**settings.__dict__, "max_agent_attempts": 2}
|
||||
)
|
||||
issue = queued_issue()
|
||||
running = Issue(**{**issue.__dict__, "labels": (Label(2, "ai:running"),)})
|
||||
gitea = Mock()
|
||||
gitea.get_issue.return_value = issue
|
||||
gitea.set_automation_state.side_effect = [running, running]
|
||||
gitea.create_pull_request.return_value = PullRequest(
|
||||
18,
|
||||
"https://gitea.example.test/owner/lai/pulls/18",
|
||||
)
|
||||
agent = Mock()
|
||||
agent.run.side_effect = [
|
||||
AgentResult("Submitted", "First", 4, 0.2),
|
||||
AgentResult("Submitted", "Repaired", 2, 0.1),
|
||||
]
|
||||
workspace = GitWorkspace.return_value
|
||||
workspace.path = settings.workspace_root / "issue-7" / "repo"
|
||||
workspace.branch = "ai/issue-7"
|
||||
workspace.summary.return_value = ChangeSummary(("app/Fix.php",), 2, 0)
|
||||
workspace.normalize_changed_whitespace.return_value = ()
|
||||
workspace.has_symlink.return_value = False
|
||||
workspace.has_path.return_value = False
|
||||
workspace.run_trusted.side_effect = [
|
||||
Mock(),
|
||||
RuntimeError("PHP parse error on line 3"),
|
||||
Mock(),
|
||||
]
|
||||
workspace.commit.return_value = "abc123"
|
||||
|
||||
Worker(settings, gitea, agent).process(issue, labels())
|
||||
|
||||
assert agent.run.call_count == 2
|
||||
assert "PHP parse error on line 3" in agent.run.call_args_list[1].args[3]
|
||||
workspace.push.assert_called_once()
|
||||
assert gitea.set_automation_state.call_args_list[-1].args[1] == "ai:ready"
|
||||
|
||||
|
||||
@patch("lai_automation.worker.GitWorkspace")
|
||||
def test_preflight_runs_setup_and_tests_without_model(
|
||||
GitWorkspace,
|
||||
|
||||
Reference in New Issue
Block a user