# Canonical scaffolding policy for Python conformance libraries.
#
# `mgf-fed drift-check` enforces this: every Python member should carry the standard
# scaffolding, the canonical CI step-set, the gate config, and the byte-identical shared
# files. Complements `cookiecutter-mgf-project` (which *generates*; this *verifies*).
schema = 1

# Files that MUST exist (repo-relative).
present = [
    ".woodpecker.yml",
    ".gitleaks.toml",
    "scripts/verify_codeberg.py",
    "PUBLIC_API.json",
    "tools/generate_public_api_json.py",
    "docs/inprogress/MGF_STANDARDS_CONFORMANCE.md",
    "SCOPE.md",
    "DEPS.md",
]
py_typed = true   # require a src/**/py.typed marker (PEP 561)

# The .woodpecker.yml is a GENERATED artifact (mgf.fed._woodpecker.render_woodpecker):
# `mgf-fed scaffold` writes the rendered pipeline and `mgf-fed drift-check` flags any
# on-disk file that diverges from a fresh render. Every member is generated (python from
# base.yml + frag-*.yml; Zig from base-zig.yml) EXCEPT the legitimately-bespoke pipelines
# listed in [exempt].woodpecker — those skip the generation-currency comparison and fall
# back to the step-name list below (WF-13).
woodpecker_generated = true

# FALLBACK ONLY (used when generation cannot run — e.g. an unparseable pyproject.toml
# makes render_woodpecker raise): the .woodpecker step names that must ALL be present.
# When woodpecker_generated is true and a render succeeds, the generation-currency
# check (on-disk == fresh render) supersedes this name-list. Per-shape extras allowed:
# zig-build-and-test, supervisor-tier-*, nightly-*.
# NOTE: top-level array — must precede every [table] header or TOML nests it.
woodpecker_required_steps = [
    "lint", "commit-trailers", "typecheck",
    "test-3.11", "test-3.12", "test-3.13",
    "vuln-scan", "secret-scan",
    "build", "sbom",
    "tag-coherence", "smoke", "publish", "verify-devpi",
]

# Files that must byte-match the template copy (value = path under templates/).
[exact]
"scripts/verify_codeberg.py" = "verify_codeberg.py"
# The commit-trailers CI step (AG-03, generated for every member) runs this
# script; ship it byte-exact so a freshly-scaffolded repo doesn't fail the gate
# with file-not-found. Repos whose CI has no commit-trailers step simply carry
# an unused copy (harmless); repos that have it already match this canonical.
"scripts/check_commit_trailers.py" = "check_commit_trailers.py"
".gitleaks.toml" = "gitleaks.toml"
# AG-18 — the local prepare-commit-msg hook (so `git commit -m` keeps the AG-03
# Signed-off-by). Sourced from the cookiecutter's canonical copy; the scaffold
# writer chmods .githooks/* +x so the committed hook is executable. Without it a
# freshly-scaffolded repo fails app-doctor's AG-18 gate until `catch-up` runs.
".githooks/prepare-commit-msg" = "cookiecutter-mgf-project/{{cookiecutter.project_slug}}/.githooks/prepare-commit-msg"

# pyproject.toml policy (parsed, not grepped).
[pyproject]
build_backend = "hatchling.build"
mypy_strict = true                 # [tool.mypy] strict = true
pytest_filterwarnings_error = true # [tool.pytest.ini_options] filterwarnings starts with "error"
standards_extra = true             # a separate [project.optional-dependencies].standards
ruff_spec = "ruff>=0.4,<0.16"      # exact canonical dev pin — fleet is 0.15.x-formatted, so
                                   # <0.16 prevents a future 0.16 reformatting + breaking CI.
                                   # Enforced exactly (the weaker "<1" is no longer accepted).

# Per-shape exemptions: repos legitimately excused from a specific check, with the reason.
[exempt]
standards_extra = ["mgf-standard"]  # IS the standard — a self-referential mgf-common[standards] dep is circular

# Repos with an intentionally-bespoke .woodpecker.yml, excused from the generation-currency
# check (on-disk == fresh render) and instead held to the step-name fallback
# (woodpecker_required_steps all present). mgf-hrb runs a Zig build + the multi-tier
# supervisor pipeline; mgf-test-supervisor runs its own slow-suite tier — neither is rendered
# from the canonical template, so `mgf-fed scaffold` leaves their pipeline untouched (WF-13).
woodpecker = ["mgf-hrb", "mgf-test-supervisor"]
