"""Doc-contract checks for the shell-spawn hard-stop rule (#258).

When the shell executor fails to spawn (exit_code: -1 with empty
stdout/stderr), agents must probe once, mark shell unavailable, hard-stop
after two consecutive spawn failures, and emit a recovery report instead of
retry-spiralling. These tests pin that guidance in the runbooks, the portable
skill doc, and the operator guide so it cannot silently regress.
"""
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent.parent

RUNBOOK = REPO_ROOT / "docs" / "llm-workflow-runbooks.md"
SKILL = REPO_ROOT / "skills" / "llm-project-workflow" / "SKILL.md"


def _normalize(text: str) -> str:
    """Collapse whitespace so phrase checks survive markdown line wrapping."""
    return " ".join(text.split())


def _runbook_text() -> str:
    return _normalize(RUNBOOK.read_text(encoding="utf-8"))


def _skill_text() -> str:
    return _normalize(SKILL.read_text(encoding="utf-8"))


def test_runbook_has_shell_spawn_hard_stop_section():
    text = _runbook_text()
    assert "## Shell Spawn Hard-Stop Rule" in text
    for phrase in (
        "exit_code: -1",
        "empty stdout/stderr",
        "trivial probe",
        "two consecutive spawn failures",
        "mark shell unavailable",
        "recovery report",
    ):
        assert phrase in text, f"runbook missing phrase: {phrase!r}"


def test_runbook_recovery_report_names_required_steps():
    text = _runbook_text()
    for phrase in (
        "restart the session",
        "kill hung background terminals",
        "MCP-native",
    ):
        assert phrase in text, f"runbook recovery guidance missing: {phrase!r}"


def test_runbook_forbids_retry_spirals():
    text = _runbook_text()
    assert "never retry the same failing spawn" in text


def test_skill_doc_declares_shell_spawn_hard_stop_rule():
    text = _skill_text()
    assert "## Shell Spawn Hard-Stop Rule" in text
    for phrase in (
        "exit_code: -1",
        "two consecutive spawn failures",
        "recovery report",
    ):
        assert phrase in text, f"SKILL.md missing phrase: {phrase!r}"


def test_operator_guide_rules_include_shell_spawn_hard_stop():
    import sys

    sys.path.insert(0, str(REPO_ROOT))
    import gitea_mcp_server

    rule = gitea_mcp_server._GUIDE_RULES["shell_spawn_hard_stop"]
    for phrase in (
        "exit_code: -1",
        "two consecutive",
        "recovery report",
    ):
        assert phrase in rule, f"operator guide rule missing: {phrase!r}"
