"""★야외 보충 스텝은 중앙 CP 를 **앞**에 둔다 — 없으면 legacy 로 사지 않고 선다.

실측 canary 4398a55dc0bb (2026-09-03): step_manifest 에 `outdoor_structure_form_reference → reference_acquisition`
의존이 없어 닫힘(32 스텝)에 중앙이 빠졌고, `acquisition_owner` 가 OWNER_OUTDOOR 를 돌려줘 야외 스텝이 제 legacy
경로로 5라운드(제공자 4회)를 샀다. 보충 CP 0 · journal 0 · projected_from None."""
from __future__ import annotations

import pytest

from app.core.step_manifest import STEP_MANIFEST as M
from app.modules.pipeline import reference_acquisition as ra


class TestTheDependencyIsDeclared:
    def test_the_outdoor_step_depends_on_the_central_acquisition(self):
        deps = list(M["outdoor_structure_form_reference"]["depends_on"])
        assert "reference_acquisition" in deps
        # ★순서도 앞이다 — 의존만 적고 순서가 뒤면 run-all 이 막힌다
        assert float(M["reference_acquisition"]["order"]) < float(M["outdoor_structure_form_reference"]["order"])

    def test_the_canary_closure_now_carries_the_central_step(self):
        from tools.grounding_audit import canary_cost_table as ct
        got = ct.execution_steps_to("outdoor_structure_form_reference")
        assert "reference_acquisition" in got and "grounding_screen" in got


class TestABuyingModeWithoutTheFrontStops:
    @pytest.mark.parametrize("mode", ["v2", "v2_chunk"])
    def test_the_owner_rule_raises_instead_of_falling_back(self, mode):
        with pytest.raises(ra.FrontCheckpointMissing) as e:
            ra.acquisition_owner(mode, front_checkpoint_exists=False)
        assert "reference_acquisition" in str(e.value)
        assert ra.acquisition_owner(mode, front_checkpoint_exists=True) == ra.OWNER_FRONT

    def test_a_non_buying_mode_keeps_the_explicit_legacy_owner(self):
        assert ra.acquisition_owner("legacy", front_checkpoint_exists=False) == ra.OWNER_OUTDOOR

    def test_the_step_turns_it_into_a_422_before_any_purchase(self, tmp_path, monkeypatch):
        from app.core.config import settings
        from app.core.errors import AppError
        import app.core.steps.outdoor_structure_form_reference_step as m
        monkeypatch.setattr(settings, "projects_dir", str(tmp_path / "projects"))
        st = m.OutdoorStructureFormReferenceStep.__new__(m.OutdoorStructureFormReferenceStep)
        st.project_id, st.episode_id = "p", "e"
        st.project_config = {"grounding_mode": "v2_chunk"}
        st._config_hash = lambda: "cfg"
        st._load_prev_checkpoint = lambda sid: None            # ★중앙 CP 없음
        bought = []
        monkeypatch.setattr(m, "run_round", lambda *a, **k: bought.append(a), raising=False)
        with pytest.raises(AppError) as e:
            st._execute()
        assert e.value.status_code == 422 and e.value.code == "form_reference.front_missing"
        assert bought == []
