#!/usr/bin/env python3
"""Pilot-gate check with explicit executable evidence requirements.

Artifact presence is inventory only and never a pass. Each check requires a
real evidence record with `executed: true` and a SHA-256 hash of the resulting
command output, report, transaction manifest, or monitoring record. The
checked-in evidence template intentionally contains no passing evidence.

Usage:
    python3 pr8/pilot/check_pilot_gate.py
    python3 pr8/pilot/check_pilot_gate.py --evidence /secure/path/evidence.json
"""
from __future__ import annotations

import argparse
import hashlib
import json
import re
from pathlib import Path
from typing import Any

ROOT = Path(__file__).resolve().parents[2]
DEFAULT_EVIDENCE = ROOT / "pr8/pilot/pilot_gate_evidence.json"
SHA256 = re.compile(r"^[a-fA-F0-9]{64}$")


def _exists(rel: str) -> bool:
    return (ROOT / rel).exists()


def _load_evidence(path: Path) -> tuple[dict[str, Any], str | None]:
    try:
        value = json.loads(path.read_text())
    except (FileNotFoundError, json.JSONDecodeError) as exc:
        return {}, str(exc)
    if not isinstance(value, dict):
        return {}, "Evidence root must be a JSON object."
    return value, None


def _record_is_executable(record: Any) -> bool:
    return (
        isinstance(record, dict)
        and record.get("executed") is True
        and isinstance(record.get("sha256"), str)
        and SHA256.fullmatch(record["sha256"]) is not None
    )


def _external_is_complete(evidence: dict[str, Any], key: str) -> bool:
    return _record_is_executable(evidence.get("external", {}).get(key))


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--evidence", type=Path, default=DEFAULT_EVIDENCE)
    args = parser.parse_args()

    evidence, evidence_error = _load_evidence(args.evidence)
    evidence_checks = evidence.get("checks", {}) if isinstance(evidence.get("checks"), dict) else {}

    definitions = [
        ("consent", "Mutual consent works", "v3-src/contracts/bonds/PartnershipBondV3Safe.sol",
         "Run Foundry fuzz on createBond with mismatched signatures."),
        ("identity_and_mandate", "Identity + mandate binding works", "v3-src/contracts/mandate/MandateRegistryV3.sol",
         "Run an integration test proving privileged actions require a registered mandate."),
        ("principal_redemption", "Principal redemption works", "v3-src/contracts/bonds/PullPaymentsV3.sol",
         "Run a withdrawal test while the relevant parent contract is paused."),
        ("liabilities_bounded", "Liabilities fully funded and bounded", "v3-src/contracts/bonds/RewardProgramV3.sol",
         "Run reserve-bound tests against deployed pilot bytecode."),
        ("disputes", "Disputes are evidence-bound and time-bounded", "v3-src/contracts/disputes/DisputeRegistryV3.sol",
         "Run finalization and default-reject tests with recorded output."),
        ("no_compromised_path", "No production fund path uses a compromised address",
         "baseline/compromised_owner_selector_scan.json", "Run the selector scan against every actual V3 address."),
        ("threshold_governance", "Governance is threshold-based", "v3-src/contracts/governance/MultisigGovernanceV3.sol",
         "Record deployed signer set, threshold, immutable floor, guardian, and target allowlist."),
        ("invariants", "All 15 invariants pass", "v3-src/test/invariants/Inv15_NoSelfBonds.t.sol",
         "Run `forge test --fuzz-runs 10000` and a recorded Base-fork run."),
        ("x402_agreement", "APIs and x402 routes agree with generated registries", "pr7/generated/openapi.json",
         "Record CI comparison against the deployed well-known endpoint."),
        ("monitoring", "Monitoring and incident procedures are live", "pr8/runbooks/MONITORING_RUNBOOK.md",
         "Record staging alerts, delivery, and a completed incident rehearsal."),
        ("caps", "V3 has strict pilot access and value caps", "v3-src/contracts/pilot/BasePilotAccessControllerV3.sol",
         "Record Base deployment, configured caps, allowlists, disabled-default checks, and hook execution."),
        ("v2_preserved", "V2 remains readable and unaffected", "baseline/V2_COMPATIBILITY_MATRIX.md",
         "Record fresh post-deploy behavior tests on all supported V2 chains."),
        ("migration_optin", "Migration is opt-in", "pr8/ui/migration-app/src/App.tsx",
         "Record reviewed deployed migration UI and explicit-consent test output."),
        ("public_docs", "Public documentation describes actual behavior", "pr8/audit/SECURITY.md",
         "Record independent documentation review of the deployed behavior."),
    ]

    checks = []
    for check_id, name, artifact, manual in definitions:
        artifact_present = _exists(artifact)
        evidence_record = evidence_checks.get(check_id)
        executable_evidence_passed = _record_is_executable(evidence_record)
        checks.append({
            "id": check_id,
            "name": name,
            "artifact": artifact,
            "artifactPresent": artifact_present,
            "requiredEvidence": {"executed": True, "sha256": "64-character SHA-256"},
            "evidence": evidence_record if isinstance(evidence_record, dict) else None,
            "executableEvidencePassed": executable_evidence_passed,
            # Kept for consumers of the old output, but it now means both
            # artifact and executable evidence are present.
            "auto": artifact_present and executable_evidence_passed,
            "manual": manual,
        })

    external_requirements = [
        "independent_audit_complete",
        "zero_unmitigated_high_findings",
        "base_fork_run_recorded",
        "multisig_signers_guardian_and_timelock_finalized",
        "v3_deployment_addresses_verified",
        "x402_payee_moved_to_multisig_treasury",
        "monitoring_alerts_live_and_rehearsed",
        "incident_runbook_rehearsed",
        "two_on_call_engineers_scheduled",
        "bug_bounty_ratified_and_live",
        "migration_ui_deployed",
        "explicit_mainnet_deployment_approval",
    ]
    failed_external = [key for key in external_requirements if not _external_is_complete(evidence, key)]
    failed_checks = [check["id"] for check in checks if not check["auto"]]
    artifact_inventory_complete = all(check["artifactPresent"] for check in checks)
    evidence_digest = hashlib.sha256(args.evidence.read_bytes()).hexdigest() if args.evidence.exists() else None

    report = {
        "generatedAt": None,
        "evidencePath": str(args.evidence),
        "evidenceFileSha256": evidence_digest,
        "evidenceReadError": evidence_error,
        "totalChecks": len(checks),
        "artifactInventoryComplete": artifact_inventory_complete,
        "artifactPresenceIsNotAPass": True,
        "executableEvidencePassed": sum(1 for check in checks if check["executableEvidencePassed"]),
        "executableEvidenceFailed": failed_checks,
        "externalEvidenceFailed": failed_external,
        "localArtifactGatePassed": False,
        "pilotReadyPreliminary": False,
        "pilotReady": not evidence_error and not failed_checks and not failed_external,
        "readinessReason": (
            "Pilot remains blocked until every check and external requirement has a real executed evidence record "
            "with a SHA-256 hash. Checked-in placeholders never count as evidence."
        ),
        "checks": checks,
    }
    print(json.dumps(report, indent=2))


if __name__ == "__main__":
    main()
