diff --git a/strix/fix/prepare.py b/strix/fix/prepare.py index 3a43e36e3..9d9eb3eba 100644 --- a/strix/fix/prepare.py +++ b/strix/fix/prepare.py @@ -546,6 +546,23 @@ async def prepare_fix( # noqa: PLR0915 gaps = _verification_gaps(repair_outcome, checks, reproduction, verifier) gaps = list(dict.fromkeys(gaps)) + if repair_outcome.status is RepairStatus.BLOCKED: + manifest, summary, artifact_ref = await manifest_builder(workspace) + return _result( + context, + state=PreparationState.BLOCKED, + reason=repair_outcome.summary, + checks=checks, + reproduction=reproduction, + verifier=verifier, + gaps=gaps, + manifest=manifest, + diff_summary=summary, + artifact_ref=artifact_ref, + attempt_history=attempt_history, + started=started, + ) + if _verification_passes(checks, reproduction, verifier): manifest, summary, artifact_ref = await manifest_builder(workspace) if not manifest: @@ -589,23 +606,6 @@ async def prepare_fix( # noqa: PLR0915 started=started, ) - if repair_outcome.status is RepairStatus.BLOCKED: - manifest, summary, artifact_ref = await manifest_builder(workspace) - return _result( - context, - state=PreparationState.BLOCKED, - reason=repair_outcome.summary, - checks=checks, - reproduction=reproduction, - verifier=verifier, - gaps=gaps, - manifest=manifest, - diff_summary=summary, - artifact_ref=artifact_ref, - attempt_history=attempt_history, - started=started, - ) - if previous_workspace_digest == workspace_digest: manifest, summary, artifact_ref = await manifest_builder(workspace) return _result( diff --git a/tests/test_fix_preparation.py b/tests/test_fix_preparation.py index c09427927..822612118 100644 --- a/tests/test_fix_preparation.py +++ b/tests/test_fix_preparation.py @@ -488,6 +488,31 @@ async def test_prepare_fix_evaluates_budget_exhausted_patch(tmp_path: Path) -> N assert result.attempt_history[0].repair.turns_used == 40 +@pytest.mark.asyncio +async def test_prepare_fix_preserves_explicit_blocked_outcome(tmp_path: Path) -> None: + workspace, commit = _workspace(tmp_path) + + async def blocked( + _context: PreparationContext, + _checks: list[CheckResult], + ) -> RepairOutcome: + return RepairOutcome( + status=RepairStatus.BLOCKED, + summary="The repair requires an unavailable generated source file.", + ) + + result = await prepare_fix( + _request(_candidate(commit)), + workspace, + repair=blocked, + verify=_verified, + ) + + assert result.state is PreparationState.BLOCKED + assert result.stop_reason == "The repair requires an unavailable generated source file." + assert result.attempts == 1 + + @pytest.mark.asyncio async def test_prepare_fix_runs_repair_proposed_reproduction(tmp_path: Path) -> None: workspace, commit = _workspace(tmp_path)