"""A2 Phase 1: assert the board grounding map's cited symbols exist in the live
merged tree. Grep-based, zero spend. Guards against post-A1 stale-citation drift."""
from pathlib import Path

REPO = Path(__file__).resolve().parents[2]  # recoil/tests -> repo root

CITATIONS = [
    ("recoil/config/model_roles.json", '"storyboard": "gpt-image-2"'),
    ("recoil/pipeline/_lib/board_builder.py", "def build_and_dispatch_board("),
    ("recoil/pipeline/_lib/board_builder.py", "def render_board_finish("),
    ("recoil/pipeline/_lib/board_builder.py", "def preferred_board_artifact("),
    ("recoil/pipeline/_lib/board_builder.py", 'get_builder(board_model, "storyboard")'),
    ("recoil/pipeline/_lib/board_builder.py", 'get_builder(board_model, "storyboard_finish")'),
    ("recoil/pipeline/_lib/board_builder.py", "run_result = receipt.run_result"),
    ("recoil/pipeline/_lib/prompt_engine.py", "def _storyboard_beat_lines("),
    ("recoil/pipeline/_lib/prompt_engine.py", "def build_storyboard_strip_prompt("),
    ("recoil/pipeline/_lib/prompt_engine.py", "def build_gpt_image_2_storyboard_finish_prompt("),
    ("recoil/pipeline/_lib/prompt_engine.py", '("gpt-image-2", "storyboard"): build_storyboard_strip_prompt'),
    ("recoil/pipeline/_lib/prompt_engine.py", '("gpt-image-2", "storyboard_finish"): build_gpt_image_2_storyboard_finish_prompt'),
    ("recoil/execution/providers/flora.py", "_FLORA_MODEL_IDS = {"),
    ("recoil/execution/providers/flora.py", '_IMAGE_REF_PARAM = "image_urls"'),
    ("recoil/execution/providers/flora.py", "def direct_submit_image("),
    ("recoil/config/model_profiles.json", '"gemini-3.1-flash-image-preview"'),
    ("recoil/pipeline/orchestrator/episode_runner.py", "def board_gate_enabled("),
    ("recoil/pipeline/orchestrator/episode_runner.py", "board_ref_path=board_ref_path,"),
    ("recoil/pipeline/core/take.py", "def board_is_approved("),
    # A1 baseline A2 composes with — must still be present:
    ("recoil/pipeline/_lib/dispatch_payload.py", "def _collect_reference_images("),
    ("recoil/pipeline/_lib/dispatch_payload.py", "assert_refs_complete"),
    ("recoil/pipeline/_lib/dispatch_payload.py", "board_ref_path: Optional[str] = None"),
]


def test_all_a2_board_citations_present():
    missing = []
    for rel, needle in CITATIONS:
        text = (REPO / rel).read_text(encoding="utf-8")
        if needle not in text:
            missing.append(f"{rel} :: {needle!r}")
    assert not missing, "Stale board citations (re-ground before building):\n" + "\n".join(missing)


def test_board_model_cli_flag_absent():
    """No board CLI entry point exists; the override is a function param, not a
    --board-model flag. Confirm the flag spelling is absent across cli + tools."""
    for rel in ("recoil/pipeline/cli", "recoil/pipeline/tools"):
        d = REPO / rel
        if not d.is_dir():
            continue
        for p in d.rglob("*.py"):
            assert "board-model" not in p.read_text(encoding="utf-8"), f"--board-model in {p}"


def test_current_gpt_image_2_storyboard_builders_registered():
    """The CURRENT gpt-image-2 storyboard registrations exist (the rows Phase 2's
    NB2 entries sit BESIDE). Idempotent: asserts a present fact (does NOT assert the
    ABSENCE of the NB2 rows Phase 2 adds), so a rerun-from-Phase-1 after Phase 2 still
    passes."""
    text = (REPO / "recoil/pipeline/_lib/prompt_engine.py").read_text(encoding="utf-8")
    assert '("gpt-image-2", "storyboard"): build_storyboard_strip_prompt' in text
    assert '("gpt-image-2", "storyboard_finish"): build_gpt_image_2_storyboard_finish_prompt' in text
