"""Tests for the cross-layer audit.

The properties under test are the ones that make this different from a pile of
checks — and both encode a specific incident:

* **A check that could not run is a FAILURE, not a pass.** A dead webhook looked
  exactly like a healthy repo for three weeks because "unverified" and "verified"
  shared an exit code.
* **A skipped check still names its layer boundary.** A skip that cannot say what
  it would have compared is as opaque as no check at all.

Plus the precision the port had to gain: promoting a *census* to a *gate* raises
the bar, because a noisy row in a report is tolerable and a noisy row in a gate is
how the real findings get ignored.
"""

from __future__ import annotations

import json
import shutil
import subprocess
from pathlib import Path

import pytest

from mgf.fed import _audit
from mgf.fed._audit import (
    CHECKS,
    COMMITTED,
    DECLARED,
    CheckResult,
    Finding,
    check_feedback_status,
    check_fleet,
    run_audit,
    run_checks,
)
from mgf.fed.cli import _init_project as _IP

# --------------------------------------------------------------------------- #
# The two structural properties.
# --------------------------------------------------------------------------- #


def test_every_check_declares_the_layer_boundary_it_crosses() -> None:
    valid = {_audit.DECLARED, _audit.COMMITTED, _audit.PUBLISHED, _audit.INSTALLED, _audit.LIVE}
    for name, (_fn, _net, layers) in CHECKS.items():
        assert len(layers) == 2, name
        assert set(layers) <= valid, f"{name} names a layer that does not exist: {layers}"


def test_an_unrequested_skip_is_a_failure_not_a_pass(tmp_path: Path, monkeypatch) -> None:
    """THE property. A check that cannot run must not share an exit code with a
    check that ran clean — that equivalence is what let a dead webhook pass."""
    monkeypatch.setattr(
        _audit,
        "check_fleet",
        lambda root, **kw: CheckResult("fleet", (DECLARED, COMMITTED), skipped="no token"),
    )
    monkeypatch.setitem(CHECKS, "fleet", (_audit.check_fleet, False, (DECLARED, COMMITTED)))
    assert run_audit(["fleet"], root=tmp_path) == 1


def test_a_skip_requested_by_offline_does_not_fail_the_run(tmp_path: Path) -> None:
    # --offline is an explicit opt-in to a subset: the operator asked for it, so it
    # is not a failure. It is still NAMED in the output (asserted below).
    assert run_audit(["pypi-namespace"], offline=True, root=tmp_path) == 0


def test_offline_skips_are_named_never_silent(tmp_path: Path, capsys) -> None:
    run_audit(["pypi-namespace", "governance"], offline=True, root=tmp_path)
    out = capsys.readouterr().out
    assert "did NOT run" in out
    assert "pypi-namespace" in out and "governance" in out


def test_a_skipped_check_still_reports_its_layers(tmp_path: Path) -> None:
    # A skip that cannot say what it WOULD have compared is as opaque as no check.
    [res] = run_checks(["ci-freshness"], offline=True, root=tmp_path)
    assert res.skipped == "--offline"
    assert res.layers == (_audit.LIVE, _audit.COMMITTED)


def test_clean_run_exits_zero(tmp_path: Path, monkeypatch) -> None:
    monkeypatch.setitem(
        CHECKS,
        "fleet",
        (
            lambda root, **kw: CheckResult("fleet", (DECLARED, COMMITTED), examined=3),
            False,
            (DECLARED, COMMITTED),
        ),
    )
    assert run_audit(["fleet"], root=tmp_path) == 0


def test_findings_exit_one(tmp_path: Path, monkeypatch) -> None:
    monkeypatch.setitem(
        CHECKS,
        "fleet",
        (
            lambda root, **kw: CheckResult(
                "fleet", (DECLARED, COMMITTED), examined=1, findings=[Finding("x", "gap")]
            ),
            False,
            (DECLARED, COMMITTED),
        ),
    )
    assert run_audit(["fleet"], root=tmp_path) == 1


def test_json_output_carries_layers_and_skips(tmp_path: Path, capsys) -> None:
    run_audit(["pypi-namespace"], offline=True, json_only=True, root=tmp_path)
    data = json.loads(capsys.readouterr().out)
    assert data["offline"] is True
    assert data["skipped"] == ["pypi-namespace"]
    assert data["checks"][0]["layers"] == [_audit.PUBLISHED, _audit.DECLARED]


# --------------------------------------------------------------------------- #
# check: fleet — declared ↔ committed/disk
# --------------------------------------------------------------------------- #


def _fleet_env(tmp_path: Path, *, registry: list[str], fleet_md: list[str]) -> Path:
    (tmp_path / "mgf-standard").mkdir(parents=True)
    (tmp_path / "mgf-standard" / "MGF_LIBRARIES.json").write_text(
        json.dumps({"libraries": [{"repo": r} for r in registry]}), encoding="utf-8"
    )
    (tmp_path / "mgf").mkdir(parents=True)
    (tmp_path / "mgf" / "FLEET.md").write_text("\n".join(f"- {n}" for n in fleet_md), "utf-8")
    for r in registry:
        (tmp_path / r).mkdir(exist_ok=True)
    return tmp_path


def test_fleet_flags_a_registry_member_absent_from_fleet_md(tmp_path: Path) -> None:
    root = _fleet_env(tmp_path, registry=["mgf-a", "mgf-b"], fleet_md=["mgf-a"])
    res = check_fleet(root)
    assert [f.target for f in res.findings] == ["mgf-b"]
    assert "not named in FLEET.md" in res.findings[0].detail


def test_fleet_flags_a_registry_member_missing_from_disk(tmp_path: Path) -> None:
    root = _fleet_env(tmp_path, registry=["mgf-a"], fleet_md=["mgf-a"])
    (root / "mgf-a").rmdir()
    assert any("not on disk" in f.detail for f in check_fleet(root).findings)


def test_fleet_is_clean_when_registry_disk_and_fleet_md_agree(tmp_path: Path) -> None:
    root = _fleet_env(tmp_path, registry=["mgf-a", "mgf-b"], fleet_md=["mgf-a", "mgf-b"])
    assert check_fleet(root).ok


def test_fleet_skips_rather_than_fails_without_the_court_workspace(tmp_path: Path) -> None:
    # FLEET.md lives in the private workspace, which is not a federation member. Its
    # absence is not a defect OF THE FLEET, so it must skip — and the skip then fails
    # the run, which is the honest outcome: nothing was verified.
    (tmp_path / "mgf-standard").mkdir(parents=True)
    res = check_fleet(tmp_path)
    assert res.skipped and not res.findings


# --------------------------------------------------------------------------- #
# check: feedback-status — the precision a gate needs that a census did not
# --------------------------------------------------------------------------- #


def _feedback(tmp_path: Path, body: str) -> Path:
    (tmp_path / "mgf-x").mkdir(parents=True)
    (tmp_path / "mgf-x" / "FEEDBACK.md").write_text(body, encoding="utf-8")
    return tmp_path


def test_a_paper_without_a_status_is_flagged(tmp_path: Path) -> None:
    root = _feedback(tmp_path, "## PAPER-12 — a thing\n\nsome prose, no status\n")
    assert [f.target for f in check_feedback_status(root).findings] == ["mgf-x:PAPER-12"]


def test_a_paper_with_a_status_bullet_is_clean(tmp_path: Path) -> None:
    root = _feedback(tmp_path, "## PAPER-12 — a thing\n\n**Status:** SHIPPED\n")
    assert check_feedback_status(root).ok


def test_an_emoji_prefixed_status_still_counts(tmp_path: Path) -> None:
    # Anchoring straight to a letter reported every `✅ SHIPPED` as unstated — i.e. it
    # called resolved papers unstated, the same over-reporting class as the release gate.
    root = _feedback(tmp_path, "## PAPER-12 — a thing\n\n**Status:** ✅ SHIPPED\n")
    assert check_feedback_status(root).ok


def test_a_cohort_heading_naming_a_RANGE_is_not_a_paper(tmp_path: Path) -> None:
    """The false positive this check produced on its very first run against the real
    fleet: `(PAPER-100..106)` groups seven papers that each carry their own heading."""
    root = _feedback(
        tmp_path,
        "## Plasma cohort — filed 2026-06-11 (PAPER-100..106)\n\nAll seven resolved.\n"
        "### PAPER-100 — a real one\n\n**Status:** SHIPPED\n",
    )
    assert check_feedback_status(root).ok


def test_a_real_paper_that_merely_MENTIONS_a_range_is_still_judged(tmp_path: Path) -> None:
    """The control for the fix above. `### PAPER-100 — … + REL-10..13` is a real paper;
    a looser "contains a range" rule would silently drop it — trading a false positive
    for a false negative, which in a gate is the worse of the two."""
    root = _feedback(tmp_path, "### PAPER-100 — Index of MUSTs omits REL-10..13\n\nno status\n")
    assert [f.target for f in check_feedback_status(root).findings] == ["mgf-x:PAPER-100"]


def test_template_headings_are_not_papers(tmp_path: Path) -> None:
    root = _feedback(tmp_path, "## PAPER-NN — <one-line title>\n\nthe submission template\n")
    assert check_feedback_status(root).ok


# --------------------------------------------------------------------------- #
# Ported behaviour that must not regress.
# --------------------------------------------------------------------------- #


def test_release_ignored_covers_the_unshipped_paths(tmp_path: Path) -> None:
    """The tuned list (PAPER-130): without it the gate called 28 distributions stale
    and 26 were noise. A gate that cries wolf 26 times is how the two real findings
    get ignored — over-reporting is a correctness bug in a gate, not a safe default."""
    for unshipped in (
        "docs/x.md",
        "tests/test_x.py",
        "uv.lock",
        "PUBLIC_API.json",
        "fed-resources/a.toml",
        "CHANGELOG.md",
        ".woodpecker.yml",
        "ops/deploy.sh",
    ):
        assert _audit.RELEASE_IGNORED.match(unshipped), unshipped
    for shipped in ("src/mgf/x/__init__.py", "src/mgf/x/core.py"):
        assert not _audit.RELEASE_IGNORED.match(shipped), shipped


def test_least_privilege_secrets_are_never_widened() -> None:
    # If a repo asks for a publish credential outside its allowed events, the fix is
    # the REPO. This set exists so the gate can never recommend loosening the secret.
    assert "devpi_password" in _audit.LEAST_PRIVILEGE
    assert "codeberg_package_token" in _audit.LEAST_PRIVILEGE


def test_held_deploy_path_arming_is_a_finding() -> None:
    """The inversion: while a path is HELD, the secrets being unavailable is the
    intended state and ARMING them is the failure. Registering these publishes the
    website, which is under the founder's explicit hold."""
    doc = {
        "when": {"event": "deployment"},
        "steps": [{"name": "deploy", "environment": {"TOK": {"from_secret": "resend_api_key"}}}],
    }
    findings = _audit._scope_findings("mgf-website", doc, {"resend_api_key": {"deployment"}})
    assert any("ARMED" in f.detail for f in findings)


def test_held_deploy_path_unregistered_is_the_intended_state() -> None:
    doc = {
        "when": {"event": "deployment"},
        "steps": [{"name": "deploy", "environment": {"TOK": {"from_secret": "resend_api_key"}}}],
    }
    assert _audit._scope_findings("mgf-website", doc, {}) == []


def test_an_unregistered_secret_outside_a_held_path_is_a_finding() -> None:
    doc = {"steps": [{"name": "s", "environment": {"T": {"from_secret": "nope"}}}]}
    findings = _audit._scope_findings("mgf-other", doc, {})
    assert findings and "dies at COMPILE" in findings[0].detail


def test_clone_and_services_demand_every_pipeline_event() -> None:
    # They are never pruned by a step-level `when:` — a scope gap there kills the run.
    doc = {"when": {"event": ["push", "tag"]}, "clone": {"x": {"from_secret": "k"}}}
    assert _audit._secret_demands(doc)["k"] == {"push", "tag"}


def test_a_step_when_narrows_the_events_it_demands() -> None:
    doc = {
        "when": {"event": ["push", "tag"]},
        "steps": [
            {
                "name": "publish",
                "when": {"event": "tag"},
                "environment": {"P": {"from_secret": "devpi_password"}},
            }
        ],
    }
    assert _audit._secret_demands(doc)["devpi_password"] == {"tag"}


def test_unknown_check_names_are_rejected_not_silently_ignored() -> None:
    assert "not-a-check" not in CHECKS


@pytest.mark.parametrize("name", sorted(CHECKS))
def test_every_check_is_runnable_offline_without_raising(name: str, tmp_path: Path) -> None:
    # An empty root is the hostile case: no registry, no repos, no workspace. A check
    # must skip or report, never crash the sweep for the checks behind it.
    [res] = run_checks([name], offline=True, root=tmp_path)
    assert res.name == name


# --------------------------------------------------------------------------- #
# The committed artifact + its CI-side gate.
#
# The expensive half needs the whole federation on disk plus credentials, so it
# cannot run in a single-repo CI clone. The cheap half asks the artifact four
# questions about ITSELF — and each is a way a checker has actually died here.
# --------------------------------------------------------------------------- #


def _artifact(tmp_path: Path, **over) -> Path:
    body = {
        "generated": _audit._today(),
        "checks": [],
        "findings": 0,
        "skipped": [],
        # Every REGISTERED check, because the default is meant to read "a complete
        # artifact" — naming a fixed pair meant the fixture silently stopped being
        # complete the moment a check was added.
        "ran": list(CHECKS),
    }
    body.update(over)
    p = tmp_path / "AUDIT.json"
    p.write_text(json.dumps(body), encoding="utf-8")
    return p


def test_a_missing_artifact_fails(tmp_path: Path) -> None:
    assert _audit.check_artifact(tmp_path / "nope.json") == 1


def test_a_fresh_complete_clean_artifact_passes(tmp_path: Path) -> None:
    assert _audit.check_artifact(_artifact(tmp_path)) == 0


def test_an_unstamped_artifact_fails(tmp_path: Path, capsys) -> None:
    # An artifact with no date can never be called stale — so it would read as
    # current forever.
    assert _audit.check_artifact(_artifact(tmp_path, generated="")) == 1
    assert "UNSTAMPED" in capsys.readouterr().out


def test_a_stale_artifact_fails(tmp_path: Path, capsys) -> None:
    # The 2026-07-29 conformance tracker asserted a result from 2026-07-04 for
    # twenty-five days, because nothing was ever going to look.
    assert _audit.check_artifact(_artifact(tmp_path, generated="2020-01-01")) == 1
    assert "STALE" in capsys.readouterr().out


def test_an_INCOMPLETE_artifact_fails_even_with_zero_findings(tmp_path: Path, capsys) -> None:
    """THE property. An artifact from an --offline run carries real numbers and covers
    half the boundaries. Zero findings across the checks that RAN is not a clean audit,
    and must never be allowed to read as one."""
    art = _artifact(tmp_path, findings=0, skipped=["ci-freshness", "governance"])
    assert _audit.check_artifact(art) == 1
    out = capsys.readouterr().out
    assert "INCOMPLETE" in out and "ci-freshness" in out


def test_an_artifact_with_findings_fails(tmp_path: Path) -> None:
    assert _audit.check_artifact(_artifact(tmp_path, findings=3)) == 1


def test_an_unreadable_artifact_fails(tmp_path: Path) -> None:
    p = tmp_path / "AUDIT.json"
    p.write_text("{ not json", encoding="utf-8")
    assert _audit.check_artifact(p) == 1


def test_the_artifact_records_what_did_NOT_run(tmp_path: Path) -> None:
    run_audit(
        ["pypi-namespace", "fleet"],
        offline=True,
        root=tmp_path,
        write=tmp_path / "AUDIT.json",
        when="2026-07-30",
    )
    data = json.loads((tmp_path / "AUDIT.json").read_text())
    assert "pypi-namespace" in data["skipped"]
    assert data["generated"] == "2026-07-30"


def test_an_offline_artifact_does_not_satisfy_the_gate(tmp_path: Path) -> None:
    # End-to-end of the property above: writing an offline artifact and then gating
    # it must FAIL, however clean the checks that ran happened to be.
    run_audit(
        ["pypi-namespace", "fleet"],
        offline=True,
        root=tmp_path,
        write=tmp_path / "AUDIT.json",
        when=_audit._today(),
    )
    assert _audit.check_artifact(tmp_path / "AUDIT.json") == 1


def test_the_audits_own_artifact_is_not_shipped_source(tmp_path: Path) -> None:
    """`AUDIT.json` is this module's committed artifact — a repo-root governance file
    that no wheel ships. Leaving it out made the audit report the very repo that stores
    its results, one hour after the same gate taught us the same lesson about
    `AGENTS.md`. Two entries in one session, from opposite directions: an exclusion
    list decays, and it decays fastest right after you add something to the repo."""
    assert _audit.RELEASE_IGNORED.match("AUDIT.json")


# --------------------------------------------------------------------------- #
# Shipped-ness is read from the build config, not guessed.
#
# RELEASE_IGNORED existed because we were GUESSING what a wheel contains. It
# decayed twice in one session (AGENTS.md, AUDIT.json) — noise — and, worse, it
# UNDER-reported: mgf-standard force-includes docs/standards into its wheel while
# the list excludes docs/, so a change to the standards corpus (the repo's entire
# product) would have shipped unnoticed. Over-reporting is noise; under-reporting
# is a gate that lies.
# --------------------------------------------------------------------------- #

_HATCH = """
[project]
name = "mgf-x"
version = "1.0.0"
[tool.hatch.build.targets.wheel]
packages = ["src/mgf"]
force-include = {"docs/standards" = "mgf/x/_standards", "REGISTRY.json" = "mgf/x/_reg.json"}
"""


def test_force_included_paths_ship(tmp_path: Path) -> None:
    """THE under-report. A force-included directory is wheel content."""
    pkgs, forced = _audit._wheel_sources(_HATCH)
    assert _audit._ships("docs/standards/RELEASING.md", pkgs, forced)
    assert _audit._ships("REGISTRY.json", pkgs, forced)


def test_the_old_exclusion_list_would_have_missed_it() -> None:
    # The regression stated as a comparison, so the fix can't silently regress.
    assert _audit.RELEASE_IGNORED.match("docs/standards/RELEASING.md"), (
        "the list excludes docs/ — which is exactly why reading the build config matters"
    )


def test_package_sources_ship(tmp_path: Path) -> None:
    pkgs, forced = _audit._wheel_sources(_HATCH)
    assert _audit._ships("src/mgf/x/core.py", pkgs, forced)


def test_unshipped_paths_do_not(tmp_path: Path) -> None:
    pkgs, forced = _audit._wheel_sources(_HATCH)
    for path in ("tests/test_x.py", "AGENTS.md", "AUDIT.json", "uv.lock", "docs/OTHER.md"):
        assert not _audit._ships(path, pkgs, forced), path


def test_a_sibling_prefix_is_not_a_match() -> None:
    # `docs/standards-old/x` must not match the `docs/standards` force-include.
    pkgs, forced = _audit._wheel_sources(_HATCH)
    assert not _audit._ships("docs/standards-old/x.md", pkgs, forced)
    assert not _audit._ships("src/mgf-other/y.py", pkgs, forced)


def test_an_unreadable_config_degrades_to_the_list_and_says_so() -> None:
    # Losing the config must not silently change the verdict's basis.
    assert _audit._wheel_sources("this is not toml {{{") is None
    assert _audit._wheel_sources('[project]\nname = "x"\n') is None


# --------------------------------------------------------------------------- #
# agent-context — declared ↔ committed.
#
# Phase 2 of ONE-ESTATE installed the root pointer on 54 repos and named
# `audit --check agent-context` as its acceptance criterion. The check did not
# exist, so the mechanism shipped with nothing in any exit code able to notice it
# leaving again. These are its negative controls: every one is a defect the wave
# actually found on a real repo, and the check is only worth its exit code if each
# of them turns it red.
#
# They build REAL git repos with a real `origin`, because the check reads the
# committed tree and a fake `_git` would only prove the parser agrees with the
# fixture — the "writer and checker confirm each other" trap this check exists to
# break. That costs coverage in CI: `python:*-slim` has no `git`, so these skip
# there, as ~76 tests in this suite already do. Filed against the pipeline
# template rather than papered over — the image, not the tests, is the defect.
# --------------------------------------------------------------------------- #

#: The house convention (see ``test_feedback.py``) for tests that shell out to git.
requires_git = pytest.mark.skipif(
    shutil.which("git") is None, reason="git not on PATH (e.g. the slim CI image)"
)

_HEALTHY_DEEP = (
    f"{_IP.CLAUDE_MD_BEGIN_MARKER}\nmanaged deep context -->\n{_IP.CLAUDE_MD_END_TEXT}\n"
    "\nAuthored deep context that must stay readable.\n"
)
#: The eighteen-repo defect: the END comment is gone, so the BEGIN's `<!--` never
#: closes and every authored line below is swallowed into a comment.
_TRUNCATED_DEEP = f"{_IP.CLAUDE_MD_BEGIN_MARKER}\nmanaged deep context -->\n\nAuthored.\n"


def _root_pointer(deep: str) -> str:
    return (
        f"{_IP.CLAUDE_MD_BEGIN_MARKER}\n{_IP.root_claude_md_block(deep)}{_IP.CLAUDE_MD_END_TEXT}\n"
    )


def _git_ok(cwd: Path, *args: str) -> None:
    subprocess.run(  # noqa: S603 — fixed git argv over a tmp_path fixture
        ["git", *args],  # noqa: S607 — `git` from PATH is the house convention
        cwd=cwd,
        check=True,
        capture_output=True,
        text=True,
    )


def _member(root: Path, name: str, files: dict[str, str]) -> Path:
    """A declared member with a real `origin` the check can interrogate.

    The remote is a bare repo on disk reached over `file://`, so `ls-remote` — the
    freshness question — is exercised for real without touching the network.
    """
    bare = root / ".remotes" / f"{name}.git"
    bare.parent.mkdir(parents=True, exist_ok=True)
    _git_ok(root, "init", "--bare", "-b", "main", str(bare))
    repo = root / name
    repo.mkdir(parents=True)
    _git_ok(repo, "init", "-b", "main")
    _git_ok(repo, "config", "user.email", "t@example.invalid")
    _git_ok(repo, "config", "user.name", "T")
    for rel, body in files.items():
        path = repo / rel
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text(body, encoding="utf-8")
    _git_ok(repo, "add", "-A")
    _git_ok(repo, "-c", "commit.gpgsign=false", "commit", "-m", "seed")
    _git_ok(repo, "remote", "add", "origin", f"file://{bare}")
    _git_ok(repo, "push", "-u", "origin", "main")
    return repo


def _fed(tmp_path: Path, members: dict[str, dict[str, str]]) -> Path:
    """A federation root declaring exactly `members` in MGF_LIBRARIES.json."""
    std = tmp_path / "mgf-standard"
    std.mkdir(parents=True)
    (std / "MGF_LIBRARIES.json").write_text(
        json.dumps({"libraries": [{"repo": n} for n in members]}), encoding="utf-8"
    )
    for name, files in members.items():
        _member(tmp_path, name, files)
    return tmp_path


def _healthy(deep: str = _IP.CANONICAL_DEEP_CONTEXT) -> dict[str, str]:
    return {"CLAUDE.md": _root_pointer(deep), deep: _HEALTHY_DEEP}


def _findings(root: Path) -> list[str]:
    res = _audit.check_agent_context(root)
    return [f.detail for f in res.findings]


@requires_git
def test_agent_context_is_clean_when_the_pointer_is_present_and_resolves(tmp_path: Path) -> None:
    """The positive control. Without it, every red below could be red for free."""
    root = _fed(tmp_path, {"mgf-thing": _healthy()})
    res = _audit.check_agent_context(root)
    assert res.findings == []
    assert res.examined == 1
    assert res.ok


@requires_git
def test_a_deleted_root_claude_md_turns_the_check_red(tmp_path: Path) -> None:
    """Phase 2's acceptance names this exact experiment."""
    files = _healthy()
    del files["CLAUDE.md"]
    root = _fed(tmp_path, {"mgf-thing": files})
    assert any("no root CLAUDE.md" in d for d in _findings(root))


@requires_git
def test_a_root_file_without_the_managed_block_is_a_finding(tmp_path: Path) -> None:
    files = _healthy() | {"CLAUDE.md": "# Hand-written, no markers\n"}
    root = _fed(tmp_path, {"mgf-thing": files})
    assert any("carries no managed block" in d for d in _findings(root))


@requires_git
def test_a_pointer_naming_a_file_that_does_not_exist_is_a_finding(tmp_path: Path) -> None:
    """The sharpest defect the wave found: green by every check, useless to the agent.

    Writer and checker compared the block against the same constant, so neither
    ever consulted the repo. This one asks the tree.
    """
    root = _fed(tmp_path, {"mgf-thing": {"CLAUDE.md": _root_pointer(_IP.CANONICAL_DEEP_CONTEXT)}})
    assert any("does NOT exist" in d for d in _findings(root))


@requires_git
def test_a_legacy_only_repo_with_a_legacy_pointer_is_CLEAN(tmp_path: Path) -> None:
    """PAPER-54 left `docs/CLAUDE.md` valid and catch-up deliberately does not move
    those repos. A checker that demanded the canonical path would flag every one of
    them — a false positive is how a real finding gets ignored."""
    root = _fed(tmp_path, {"mgf-thing": _healthy(_audit.LEGACY_DEEP_CONTEXT)})
    assert _findings(root) == []


@requires_git
def test_a_legacy_repo_carrying_the_CANONICAL_pointer_is_a_finding(tmp_path: Path) -> None:
    """The five-repo bug, exactly: legacy tree, canonical pointer, dangling."""
    files = {
        "CLAUDE.md": _root_pointer(_IP.CANONICAL_DEEP_CONTEXT),
        _audit.LEGACY_DEEP_CONTEXT: _HEALTHY_DEEP,
    }
    root = _fed(tmp_path, {"mgf-thing": files})
    assert any("has drifted" in d for d in _findings(root))


@requires_git
def test_an_unterminated_managed_block_in_the_deep_file_is_a_finding(tmp_path: Path) -> None:
    """`mgf-common` shipped 696 lines of authored deep context inside a comment."""
    files = _healthy() | {_IP.CANONICAL_DEEP_CONTEXT: _TRUNCATED_DEEP}
    root = _fed(tmp_path, {"mgf-thing": files})
    assert any("END marker(s)" in d for d in _findings(root))


@requires_git
def test_unbalanced_html_comments_in_the_deep_file_are_a_finding(tmp_path: Path) -> None:
    files = _healthy() | {_IP.CANONICAL_DEEP_CONTEXT: _HEALTHY_DEEP + "\n<!-- stray\n"}
    root = _fed(tmp_path, {"mgf-thing": files})
    assert any("unbalanced HTML comments" in d for d in _findings(root))


@requires_git
def test_a_declared_member_absent_from_disk_is_a_finding_not_a_silent_pass(tmp_path: Path) -> None:
    root = _fed(tmp_path, {"mgf-thing": _healthy()})
    (root / "mgf-standard" / "MGF_LIBRARIES.json").write_text(
        json.dumps({"libraries": [{"repo": "mgf-thing"}, {"repo": "mgf-ghost"}]}), encoding="utf-8"
    )
    assert any("not on disk" in d for d in _findings(root))


@requires_git
def test_a_STALE_view_of_origin_main_is_a_finding(tmp_path: Path) -> None:
    """The working tree is never consulted, so the remote-tracking ref IS the
    evidence — and an unfetched ref answers a question nobody asked. Auditing it
    and printing PASS is the same "unverified reads as verified" equivalence the
    module exists to break."""
    root = _fed(tmp_path, {"mgf-thing": _healthy()})
    repo = root / "mgf-thing"
    # Move the forge on without fetching: a second clone pushes, we do not pull.
    other = tmp_path / "elsewhere"
    _git_ok(tmp_path, "clone", f"file://{root / '.remotes' / 'mgf-thing.git'}", str(other))
    _git_ok(other, "config", "user.email", "t@example.invalid")
    _git_ok(other, "config", "user.name", "T")
    (other / "NEW.md").write_text("moved on\n", encoding="utf-8")
    _git_ok(other, "add", "-A")
    _git_ok(other, "-c", "commit.gpgsign=false", "commit", "-m", "forge moves on")
    _git_ok(other, "push", "origin", "main")
    assert repo.is_dir()
    assert any("STALE" in d for d in _findings(root))


@requires_git
def test_the_check_reads_the_COMMITTED_tree_not_the_working_one(tmp_path: Path) -> None:
    """Trees across this estate are routinely parked on other branches. A filesystem
    read scored a merged repo as missing and undercounted by three."""
    root = _fed(tmp_path, {"mgf-thing": _healthy()})
    (root / "mgf-thing" / "CLAUDE.md").unlink()  # merged on main, absent on disk
    assert _findings(root) == []


def test_agent_context_skips_rather_than_guesses_without_the_registry(tmp_path: Path) -> None:
    res = _audit.check_agent_context(tmp_path)
    assert res.skipped
    assert not res.ok  # a skip is not a pass


def test_a_check_REGISTERED_SINCE_the_artifact_was_written_makes_it_incomplete(
    tmp_path: Path, capsys
) -> None:
    """The artifact asked only "what was skipped?", and a check added later is in
    neither list — so a whole boundary could go unexamined while the gate stayed
    green. That is this module's own failure class, one layer up."""
    path = _artifact(tmp_path, ran=[n for n in CHECKS if n != "agent-context"], skipped=[])
    assert _audit.check_artifact(path) == 1
    assert "registered since" in capsys.readouterr().out


def test_an_artifact_that_accounts_for_every_registered_check_passes(tmp_path: Path) -> None:
    assert _audit.check_artifact(_artifact(tmp_path, ran=list(CHECKS), skipped=[])) == 0


# --------------------------------------------------------------------------- #
# conformance-ledgers — declared ↔ committed.
#
# On 2026-08-03 an mgf-standard release published five releases' worth of corpus
# in one act: 33 new MUSTs went live, no repo's ledger had a row for any of them,
# and `app-doctor` went red fleet-wide minutes later. The corpus footer had
# recorded the required follow-up wave each time and each time it was deferred.
# The debt was written down; nothing was watching it. This is the watcher.
# --------------------------------------------------------------------------- #

_INDEX = """\
# Standards

## Index of MUSTs

| Rule | Family | Text |
|---|---|---|
| AG-01 | AGENTS | a thing |
| SEAT-01 | SEATS | another thing |

## Something else

| NOT-99 | X | outside the index — must not count |
"""


def _corpus(root: Path, readme: str, members: list[str]) -> None:
    """An mgf-standard checkout whose COMMITTED main carries the corpus."""
    _member(
        root,
        "mgf-standard",
        {
            "docs/standards/README.md": readme,
            "MGF_LIBRARIES.json": json.dumps({"libraries": [{"repo": m} for m in members]}),
        },
    )


def _ledger(*ids: str) -> dict[str, str]:
    rows = "\n".join(f"| {i} | ✅ | evidence | notes |" for i in ids)
    return {"docs/inprogress/MGF_STANDARDS_CONFORMANCE.md": f"# Ledger\n\n{rows}\n"}


@requires_git
def test_only_the_index_of_musts_table_counts(tmp_path: Path) -> None:
    """A rule id elsewhere in the README is not a declared MUST — over-counting
    would make every ledger permanently short, and a gate that can never go green
    is a gate everyone learns to ignore."""
    assert _audit.index_of_musts(_INDEX) == {"AG-01", "SEAT-01"}


@requires_git
def test_a_ledger_accounting_for_every_declared_must_is_clean(tmp_path: Path) -> None:
    _corpus(tmp_path, _INDEX, ["mgf-thing"])
    _member(tmp_path, "mgf-thing", _ledger("AG-01", "SEAT-01"))
    res = _audit.check_conformance_ledgers(tmp_path)
    assert res.findings == []
    assert res.examined == 1


@requires_git
def test_an_unaccounted_must_is_a_finding_that_NAMES_it(tmp_path: Path) -> None:
    _corpus(tmp_path, _INDEX, ["mgf-thing"])
    _member(tmp_path, "mgf-thing", _ledger("AG-01"))
    [f] = _audit.check_conformance_ledgers(tmp_path).findings
    assert "SEAT-01" in f.detail
    assert "1 of 2" in f.detail or "1 unaccounted" in f.detail


@requires_git
def test_a_member_with_no_ledger_at_all_is_a_finding(tmp_path: Path) -> None:
    _corpus(tmp_path, _INDEX, ["mgf-thing"])
    _member(tmp_path, "mgf-thing", {"README.md": "no ledger here\n"})
    [f] = _audit.check_conformance_ledgers(tmp_path).findings
    assert "MGF_STANDARDS_CONFORMANCE" in f.detail


@requires_git
def test_the_corpus_is_read_from_mgf_standards_COMMITTED_main(tmp_path: Path) -> None:
    """THE regression test. The first draft took the MUST index from the INSTALLED
    corpus, the way app-doctor legitimately does — and on the bench that wrote it
    the installed corpus was 0.1.66, nine releases stale. It reported 268 declared
    MUSTs while mgf-standard's main declared 306. A check answering "would
    publishing redden the fleet?" cannot ask this laptop's wheel.

    Here the working tree is edited to DROP a MUST; the committed corpus still
    declares it, so the finding must survive.
    """
    _corpus(tmp_path, _INDEX, ["mgf-thing"])
    _member(tmp_path, "mgf-thing", _ledger("AG-01"))
    (tmp_path / "mgf-standard" / "docs" / "standards" / "README.md").write_text(
        _INDEX.replace("| SEAT-01 | SEATS | another thing |\n", ""), encoding="utf-8"
    )
    [f] = _audit.check_conformance_ledgers(tmp_path).findings
    assert "SEAT-01" in f.detail, "the check read the working tree, not the committed corpus"


@requires_git
def test_the_ledger_is_read_from_the_members_COMMITTED_main(tmp_path: Path) -> None:
    _corpus(tmp_path, _INDEX, ["mgf-thing"])
    _member(tmp_path, "mgf-thing", _ledger("AG-01", "SEAT-01"))
    (tmp_path / "mgf-thing" / "docs" / "inprogress" / "MGF_STANDARDS_CONFORMANCE.md").unlink()
    assert _audit.check_conformance_ledgers(tmp_path).findings == []


def test_conformance_ledgers_skips_rather_than_guesses_without_the_corpus(tmp_path: Path) -> None:
    res = _audit.check_conformance_ledgers(tmp_path)
    assert res.skipped and not res.ok  # a skip is not a pass
