#!/usr/bin/env python3
"""One-use, profile-scoped Task25 cleanup controller; it never sends a message."""
from __future__ import annotations

import argparse
import ctypes
import datetime as dt
import fcntl
import hashlib
import json
import os
import select
import shutil
import stat
import struct
import subprocess
import sys
import tempfile
import time
from pathlib import Path
from typing import Any

import yaml

ROOT = Path("/home/cube/projects/richard/traning coach")
EVIDENCE = ROOT / ".omo/evidence"
PROFILE = Path("/home/cube/.hermes/profiles/dualcoachtest")
OTHER = Path("/home/cube/.hermes/profiles/physique-coach")
REPO = Path("/home/cube/projects/richard/hermes-agent")
SERVICE = "hermes-gateway-dualcoachtest.service"
TOKEN = "c8eab7b6685c3c65"
SYNTHETIC = "task22_dm_rehearsal"
JOB_ID = "f674c42b57d8"
APPROVAL = "TASK25_SYNTHETIC_REHEARSAL_CLEANUP_APPROVED"
CHECKPOINT = EVIDENCE / "task25-live-cleanup-checkpoint.json"
TERMINAL = EVIDENCE / "dualcoach-task-25-live-terminal-evidence.json"
TASK24_INDEX = EVIDENCE / "dualcoach-task-24-evidence-index.json"
TASK24_TERMINAL = EVIDENCE / "dualcoach-task-24-live-terminal-evidence.json"
PINS = EVIDENCE / "dualcoach-task-24-live-deployment-pins.json"


def sha(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest()


def load(path: Path, default: Any) -> Any:
    return json.loads(path.read_text(encoding="utf-8")) if path.exists() else default


def atomic(path: Path, value: dict[str, Any]) -> None:
    fd, temporary = tempfile.mkstemp(prefix=".task25.", dir=str(path.parent))
    try:
        os.fchmod(fd, 0o600)
        with os.fdopen(fd, "w", encoding="utf-8") as stream:
            json.dump(value, stream, sort_keys=True, indent=2)
            stream.write("\n")
            stream.flush()
            os.fsync(stream.fileno())
        os.replace(temporary, path)
        directory = os.open(path.parent, os.O_DIRECTORY)
        try:
            os.fsync(directory)
        finally:
            os.close(directory)
    finally:
        try:
            os.unlink(temporary)
        except FileNotFoundError:
            pass


def private_mode(path: Path, mode: int) -> None:
    info = path.lstat()
    if path.is_symlink() or info.st_uid != os.getuid() or stat.S_IMODE(info.st_mode) != mode:
        raise RuntimeError(f"unsafe private path: {path.name}")


def tree_digest(root: Path) -> str:
    rows: list[bytes] = []
    for path in sorted(root.rglob("*")):
        relative = path.relative_to(root).as_posix().encode("utf-8")
        info = path.lstat()
        if path.is_symlink():
            rows.append(b"L\0" + relative + b"\0" + os.readlink(path).encode("utf-8"))
        elif path.is_dir():
            rows.append(b"D\0" + relative)
        elif path.is_file():
            rows.append(b"F\0" + relative + b"\0" + hashlib.sha256(path.read_bytes()).digest())
        else:
            raise RuntimeError("other profile tree contains unsupported entry")
    return hashlib.sha256(b"\n".join(rows)).hexdigest()


def gateway_state() -> tuple[str | None, str | None]:
    value = load(PROFILE / "gateway_state.json", {})
    platforms = value.get("platforms") if isinstance(value, dict) else {}
    telegram = platforms.get("telegram") if isinstance(platforms, dict) else {}
    return (
        value.get("gateway_state") if isinstance(value, dict) else None,
        telegram.get("state") if isinstance(telegram, dict) else None,
    )


def no_profile_process() -> bool:
    for entry in Path("/proc").iterdir():
        if not entry.name.isdecimal():
            continue
        try:
            values = (entry / "environ").read_bytes().split(b"\0")
        except (FileNotFoundError, PermissionError, ProcessLookupError, OSError):
            continue
        if any(value == b"HERMES_HOME=" + os.fsencode(PROFILE) for value in values):
            return False
    return True


def configs() -> list[tuple[str, list[str], object]]:
    rows: list[tuple[str, list[str], object]] = []
    for profile in (PROFILE, OTHER):
        registry = load(profile / "customers/registry.json", {})
        enabled = [row.get("customer_key") for row in registry.get("customers", []) if isinstance(row, dict) and row.get("enabled") is True]
        config = yaml.safe_load((profile / "config.yaml").read_text(encoding="utf-8"))
        gate = config["platforms"]["telegram"]["extra"]["adaptive_nutrition"].get("delivery_enabled")
        rows.append((profile.name, enabled, gate))
    return rows


def baseline() -> tuple[dict[str, Any], str]:
    if TERMINAL.exists():
        raise RuntimeError("Task25 terminal evidence already exists")
    index = load(TASK24_INDEX, {})
    terminal = load(TASK24_TERMINAL, {})
    pins = load(PINS, {})
    if index.get("verdict") != "PASS" or terminal.get("verdict") != "PASS":
        raise RuntimeError("Task24 canonical terminal evidence is not PASS")
    if pins.get("rollback_precondition_sha256") != sha(PROFILE / "config.yaml"):
        raise RuntimeError("delivery-gate rollback pin does not match live config")
    registry = load(PROFILE / "customers/registry.json", {})
    deliveries = load(PROFILE / "data/owner-actions/draft-deliveries.json", {})
    if (
        sha(PROFILE / "customers/registry.json") != "f8949a9e158f5c72d49e379d2e9a341c5dc0d126375b1a7522cb69ee74f116f4"
        or configs() != [("dualcoachtest", [SYNTHETIC], True), ("physique-coach", [], False)]
        or len(deliveries) != 1
        or next(iter(deliveries.values())).get("draft_id") != TOKEN
        or next(iter(deliveries.values())).get("status") != "sent_audited"
        or not isinstance(registry.get("customers"), list)
    ):
        raise RuntimeError("Task25 cleanup baseline drifted")
    jobs = load(PROFILE / "cron/jobs.json", {}).get("jobs")
    if not isinstance(jobs, list) or [row.get("id") for row in jobs if isinstance(row, dict)] != [JOB_ID] or jobs[0].get("enabled") is not False:
        raise RuntimeError("rehearsal cron baseline drifted")
    claims = PROFILE / "data/customer-schedule-claims"
    child = claims / SYNTHETIC
    for path in (claims, child):
        private_mode(path, 0o775)
        if not path.is_dir():
            raise RuntimeError("legacy schedule claims baseline is malformed")
    if sorted(path.name for path in claims.iterdir()) != [SYNTHETIC]:
        raise RuntimeError("legacy schedule claims baseline is not sole synthetic target")
    if subprocess.run(["systemctl", "--user", "is-active", "--quiet", SERVICE], check=False).returncode != 0:
        raise RuntimeError("rehearsal gateway is not active for the sealed cleanup boundary")
    if gateway_state() != ("running", "connected"):
        raise RuntimeError("rehearsal gateway polling baseline is not connected")
    other_digest = tree_digest(OTHER)
    bound = {
        "task24_terminal_sha256": sha(TASK24_TERMINAL),
        "task24_index_sha256": sha(TASK24_INDEX),
        "rollback_pins_sha256": sha(PINS),
        "config_sha256": sha(PROFILE / "config.yaml"),
        "registry_sha256": sha(PROFILE / "customers/registry.json"),
        "deliveries_sha256": sha(PROFILE / "data/owner-actions/draft-deliveries.json"),
        "jobs_sha256": sha(PROFILE / "cron/jobs.json"),
        "other_profile_tree_sha256": other_digest,
        "reset_source_sha256": sha(REPO / "gateway/platforms/rehearsal_reset.py"),
        "reset_test_sha256": sha(REPO / "tests/gateway/test_rehearsal_reset.py"),
        "controller_sha256": sha(Path(__file__)),
    }
    return bound, hashlib.sha256(json.dumps(bound, sort_keys=True, separators=(",", ":")).encode()).hexdigest()


def checkpoint(state: str, **fields: Any) -> None:
    atomic(CHECKPOINT, {"schema": "task25-live-cleanup-checkpoint-v1", "state": state, "timestamp": dt.datetime.now(dt.timezone.utc).isoformat().replace("+00:00", "Z"), **fields})


def stop_gateway() -> None:
    subprocess.run(["systemctl", "--user", "stop", SERVICE], check=True)
    if subprocess.run(["systemctl", "--user", "is-active", "--quiet", SERVICE], check=False).returncode == 0 or not no_profile_process():
        raise RuntimeError("gateway failed to reach a stopped runtime")


def clear_stale_gateway_lock() -> int:
    path = PROFILE / "gateway.lock"
    if not path.exists() and not path.is_symlink():
        return 0
    info = path.lstat()
    if path.is_symlink() or not stat.S_ISREG(info.st_mode) or info.st_uid != os.getuid() or stat.S_IMODE(info.st_mode) != 0o600:
        raise RuntimeError("gateway lock residue is unsafe")
    descriptor = os.open(path, os.O_RDWR | os.O_CLOEXEC | getattr(os, "O_NOFOLLOW", 0))
    try:
        try:
            fcntl.flock(descriptor, fcntl.LOCK_EX | fcntl.LOCK_NB)
        except BlockingIOError as exc:
            raise RuntimeError("gateway lock residue is active") from exc
    finally:
        os.close(descriptor)
    path.unlink()
    directory = os.open(path.parent, os.O_DIRECTORY)
    try:
        os.fsync(directory)
    finally:
        os.close(directory)
    return 1


def finalize_gateway_stop() -> int:
    stop_gateway()
    subprocess.run(["systemctl", "--user", "reset-failed", SERVICE], check=True)
    removed = clear_stale_gateway_lock()
    result = subprocess.run(
        ["systemctl", "--user", "show", SERVICE, "--property=ActiveState,SubState", "--value"],
        check=True,
        capture_output=True,
        text=True,
    )
    if tuple(result.stdout.splitlines()) != ("inactive", "dead") or not no_profile_process() or (PROFILE / "gateway.lock").exists():
        raise RuntimeError("gateway final stopped runtime is not truthful")
    return removed


def harden_schedule_claims() -> int:
    claims = PROFILE / "data/customer-schedule-claims"
    targets = (claims, claims / SYNTHETIC)
    for path in targets:
        private_mode(path, 0o775)
        if not path.is_dir():
            raise RuntimeError("legacy schedule claim is malformed")
    if sorted(path.name for path in claims.iterdir()) != [SYNTHETIC]:
        raise RuntimeError("legacy schedule claims include a non-synthetic target")
    for path in targets:
        path.chmod(0o700)
        private_mode(path, 0o700)
    return len(targets)


def disable_gate() -> str:
    config = PROFILE / "config.yaml"
    raw = config.read_bytes()
    previous_sha = sha(config)
    needle = b"      adaptive_nutrition:\n        enabled: true\n        delivery_enabled: true\n"
    replacement = needle.replace(b"delivery_enabled: true", b"delivery_enabled: false")
    if raw.count(needle) != 1:
        raise RuntimeError("exact enabled delivery gate is absent or ambiguous")
    updated = raw.replace(needle, replacement, 1)
    fd, temporary = tempfile.mkstemp(prefix=".task25-config.", dir=str(config.parent))
    try:
        os.fchmod(fd, 0o600)
        with os.fdopen(fd, "wb") as stream:
            stream.write(updated)
            stream.flush()
            os.fsync(stream.fileno())
        os.replace(temporary, config)
        directory = os.open(config.parent, os.O_DIRECTORY)
        try:
            os.fsync(directory)
        finally:
            os.close(directory)
    finally:
        try:
            os.unlink(temporary)
        except FileNotFoundError:
            pass
    if sha(config) == previous_sha:
        raise RuntimeError("delivery gate rollback did not change config")
    value = yaml.safe_load(config.read_text(encoding="utf-8"))
    if value["platforms"]["telegram"]["extra"]["adaptive_nutrition"].get("delivery_enabled") is not False:
        raise RuntimeError("delivery gate rollback is not disabled")
    return sha(config)


def cancel_cron() -> None:
    os.environ["HERMES_HOME"] = str(PROFILE)
    sys.path.insert(0, str(REPO))
    from cron.jobs import list_jobs, remove_job

    jobs = list_jobs(include_disabled=True)
    if [row.get("id") for row in jobs] != [JOB_ID] or remove_job(JOB_ID) is not True or list_jobs(include_disabled=True):
        raise RuntimeError("rehearsal cron cancellation failed")


def remove_private_tree(path: Path) -> int:
    if not path.exists():
        return 0
    private_mode(path, 0o700)
    count = 0
    for child in path.rglob("*"):
        info = child.lstat()
        expected = 0o700 if child.is_dir() else 0o600
        if child.is_symlink() or info.st_uid != os.getuid() or stat.S_IMODE(info.st_mode) != expected:
            raise RuntimeError("cron runtime artifact is unsafe")
        count += 1
    shutil.rmtree(path)
    return count


def clean_cron_runtime() -> int:
    removed = remove_private_tree(PROFILE / "cron/output")
    for name in (".jobs.lock", ".tick.lock"):
        path = PROFILE / "cron" / name
        if not path.exists():
            continue
        info = path.lstat()
        if path.is_symlink() or not path.is_file() or info.st_uid != os.getuid() or stat.S_IMODE(info.st_mode) not in {0o600, 0o664}:
            raise RuntimeError("cron lock artifact is unsafe")
        path.unlink()
        removed += 1
    return removed


def reset() -> tuple[str, str, int]:
    sys.path.insert(0, str(REPO))
    from gateway.platforms.rehearsal_reset import default_reset_policy, reset_rehearsal_profile, verify_rehearsal_archive

    result = reset_rehearsal_profile(PROFILE, confirm_profile="dualcoachtest", policy=default_reset_policy())
    if not verify_rehearsal_archive(result.archive_path).valid:
        raise RuntimeError("Task25 reset archive failed integrity verification")
    return result.archive_id, result.archive_digest, result.archived_scope_count


def restart_probe() -> None:
    libc = ctypes.CDLL(None, use_errno=True)
    fd = libc.inotify_init1(os.O_CLOEXEC)
    if fd < 0:
        raise OSError(ctypes.get_errno(), "inotify_init1")
    try:
        if libc.inotify_add_watch(fd, os.fsencode(str(PROFILE)), 0x00000008 | 0x00000080) < 0:
            raise OSError(ctypes.get_errno(), "inotify_add_watch")
        subprocess.run(["systemctl", "--user", "restart", SERVICE], check=True)
        deadline = time.monotonic() + 180
        while True:
            remaining = deadline - time.monotonic()
            if remaining <= 0:
                raise RuntimeError("post-cleanup restart did not publish connected polling state")
            ready, _, _ = select.select([fd], [], [], remaining)
            if not ready:
                raise RuntimeError("post-cleanup restart did not publish connected polling state")
            data = os.read(fd, 65536)
            offset = 0
            changed = False
            while offset + 16 <= len(data):
                _, _, _, length = struct.unpack_from("iIII", data, offset)
                name = data[offset + 16:offset + 16 + length].split(b"\0", 1)[0].decode("utf-8", "strict")
                offset += 16 + length
                changed = changed or name == "gateway_state.json"
            if changed and gateway_state() == ("running", "connected"):
                return
    finally:
        os.close(fd)


def terminal_verify(bound: dict[str, Any], archive_id: str, archive_digest: str, scope_count: int) -> dict[str, Any]:
    registry = load(PROFILE / "customers/registry.json", {})
    config = yaml.safe_load((PROFILE / "config.yaml").read_text(encoding="utf-8"))
    jobs = load(PROFILE / "cron/jobs.json", {}).get("jobs")
    archive = PROFILE / "data/rehearsal-reset-archives" / archive_id
    archive_deliveries = archive / "payload/data/owner-actions/draft-deliveries.json"
    terminal = load(TASK24_TERMINAL, {})
    if (
        registry.get("customers") != []
        or config["platforms"]["telegram"]["extra"]["adaptive_nutrition"].get("delivery_enabled") is not False
        or jobs != []
        or not archive_deliveries.is_file()
        or sha(archive_deliveries) != terminal["durable_file_sha256"]["draft-deliveries.json"]
        or load(archive_deliveries, {}) == {}
        or (PROFILE / "data/customer-schedule-claims").exists()
        or (PROFILE / "data/recovery-audits").exists()
        or (PROFILE / "data/onboarding/activation-readiness-v2").exists()
        or (PROFILE / "data/onboarding/task23-expired-bootstrap-supersession-v1").exists()
        or (PROFILE / "data/owner-actions/draft-deliveries.json").exists()
        or (PROFILE / "cron/output").exists()
        or (PROFILE / "cron/.jobs.lock").exists()
        or (PROFILE / "cron/.tick.lock").exists()
        or (PROFILE / "data/.rehearsal-reset-v1").exists()
        or (PROFILE / "data/.rehearsal-supplemental-quarantine-v1").exists()
        or bound["other_profile_tree_sha256"] != tree_digest(OTHER)
    ):
        raise RuntimeError("Task25 final baseline contains delivery, job, runtime, or other-profile drift")
    sys.path.insert(0, str(REPO))
    from gateway.platforms.rehearsal_reset import verify_rehearsal_archive

    verification = verify_rehearsal_archive(archive)
    if not verification.valid or verification.archive_digest != archive_digest or verification.archived_scope_count != scope_count:
        raise RuntimeError("Task25 archive final integrity verification failed")
    return {"archive_sha256": sha(archive / "manifest.json"), "archive_receipt_sha256": sha(archive / "receipt.json"), "other_profile_tree_sha256": tree_digest(OTHER)}


def partial_baseline() -> tuple[dict[str, Any], str]:
    checkpoint_value = load(CHECKPOINT, {})
    if checkpoint_value.get("state") != "DELIVERY_DISABLED_AND_JOBS_CANCELLED" or CHECKPOINT.stat().st_mode & 0o777 != 0o600:
        raise RuntimeError("Task25 resume checkpoint is not an authenticated partial cleanup")
    terminal = load(TASK24_TERMINAL, {})
    registry = load(PROFILE / "customers/registry.json", {})
    deliveries = load(PROFILE / "data/owner-actions/draft-deliveries.json", {})
    config = yaml.safe_load((PROFILE / "config.yaml").read_text(encoding="utf-8"))
    jobs = load(PROFILE / "cron/jobs.json", {}).get("jobs")
    claims = PROFILE / "data/customer-schedule-claims"
    if (
        terminal.get("verdict") != "PASS"
        or sha(PROFILE / "customers/registry.json") != "f8949a9e158f5c72d49e379d2e9a341c5dc0d126375b1a7522cb69ee74f116f4"
        or registry.get("customers", [{}])[0].get("customer_key") != SYNTHETIC
        or config["platforms"]["telegram"]["extra"]["adaptive_nutrition"].get("delivery_enabled") is not False
        or jobs != []
        or len(deliveries) != 1
        or next(iter(deliveries.values())).get("draft_id") != TOKEN
        or not no_profile_process()
        or not claims.is_dir()
    ):
        raise RuntimeError("Task25 partial cleanup state drifted")
    for path in (claims, claims / SYNTHETIC):
        private_mode(path, 0o700)
    bound = {
        "partial_checkpoint_sha256": sha(CHECKPOINT),
        "task24_terminal_sha256": sha(TASK24_TERMINAL),
        "config_sha256": sha(PROFILE / "config.yaml"),
        "registry_sha256": sha(PROFILE / "customers/registry.json"),
        "deliveries_sha256": sha(PROFILE / "data/owner-actions/draft-deliveries.json"),
        "jobs_sha256": sha(PROFILE / "cron/jobs.json"),
        "other_profile_tree_sha256": tree_digest(OTHER),
        "reset_source_sha256": sha(REPO / "gateway/platforms/rehearsal_reset.py"),
        "controller_sha256": sha(Path(__file__)),
    }
    return bound, hashlib.sha256(json.dumps(bound, sort_keys=True, separators=(",", ":")).encode()).hexdigest()


def complete_reset(bound: dict[str, Any], expected: str, *, resumed: bool, hardened: int, cron_artifacts: int, stale_gateway_artifacts: int) -> int:
    archive_id, archive_digest, scope_count = reset()
    checkpoint("RESET_COMMITTED", archive_id=archive_id, archive_digest=archive_digest, archive_scope_count=scope_count, resumed=resumed)
    restart_probe()
    if gateway_state() != ("running", "connected"):
        raise RuntimeError("post-cleanup restart polling verification failed")
    stale_gateway_artifacts += finalize_gateway_stop()
    cron_artifacts += clean_cron_runtime()
    final = terminal_verify(bound, archive_id, archive_digest, scope_count)
    result = {
        "schema_version": 1,
        "task": "25. Disable and clean the rehearsal",
        "status": "PASS",
        "scope": "dualcoachtest synthetic-only canonical cleanup; overall release remains NO-GO",
        "permission_seal": {"approval": APPROVAL, "seal": expected, "binding": bound, "resumed_after_stale_gateway_lock": resumed},
        "actions": {"delivery_gate_true_to_false": 0 if resumed else 1, "synthetic_customer_disabled_by_empty_registry": 1, "cron_jobs_cancelled": 0 if resumed else 1, "cron_runtime_artifacts_removed": cron_artifacts, "legacy_claim_directories_hardened": hardened, "stale_gateway_authorities_removed": stale_gateway_artifacts, "reset_archive_scope_count": scope_count, "controlled_restart_count": 1, "final_gateway_stop_count": 1},
        "archive": {"archive_id": archive_id, "archive_digest": archive_digest, **final},
        "terminal": {"enabled_customers": [], "delivery_gate": False, "scheduled_job_count": 0, "live_delivery_ledger_present": False, "task24_terminal_receipt_preserved_in_verified_archive": True, "other_profiles_byte_identical": True, "gateway_service": "inactive/dead", "profile_process_count": 0},
        "task24_canonical_evidence_sha256": sha(TASK24_TERMINAL),
        "recorded_at_utc": dt.datetime.now(dt.timezone.utc).isoformat().replace("+00:00", "Z"),
    }
    atomic(TERMINAL, result)
    checkpoint("COMPLETE_TASK25", archive_id=archive_id, archive_digest=archive_digest, archive_scope_count=scope_count)
    print("TASK25_TERMINAL_PASS", flush=True)
    return 0


def run() -> int:
    bound, expected = baseline()
    if os.environ.get("TASK25_CLEANUP_APPROVAL") != APPROVAL or os.environ.get("TASK25_CLEANUP_SEAL") != expected:
        raise RuntimeError("Task25 explicit cleanup permission seal is missing or stale")
    checkpoint("PREPARED", permission_seal=expected)
    stop_gateway()
    stale_gateway_artifacts = clear_stale_gateway_lock()
    checkpoint("GATEWAY_STOPPED", stale_gateway_authorities_removed=stale_gateway_artifacts)
    hardened = harden_schedule_claims()
    disable_gate()
    cancel_cron()
    cron_artifacts = clean_cron_runtime()
    checkpoint("DELIVERY_DISABLED_AND_JOBS_CANCELLED", hardened_claim_directories=hardened, cron_runtime_artifacts_removed=cron_artifacts)
    return complete_reset(bound, expected, resumed=False, hardened=hardened, cron_artifacts=cron_artifacts, stale_gateway_artifacts=stale_gateway_artifacts)


def resume() -> int:
    bound, expected = partial_baseline()
    if os.environ.get("TASK25_CLEANUP_APPROVAL") != APPROVAL or os.environ.get("TASK25_CLEANUP_RESUME_SEAL") != expected:
        raise RuntimeError("Task25 explicit resume permission seal is missing or stale")
    stale_gateway_artifacts = clear_stale_gateway_lock()
    checkpoint("RESUMING_RESET", permission_seal=expected, stale_gateway_authorities_removed=stale_gateway_artifacts)
    return complete_reset(bound, expected, resumed=True, hardened=0, cron_artifacts=0, stale_gateway_artifacts=stale_gateway_artifacts)


def finalization_baseline() -> tuple[dict[str, Any], str]:
    terminal = load(TERMINAL, {})
    checkpoint_value = load(CHECKPOINT, {})
    lock = PROFILE / "gateway.lock"
    if (
        terminal.get("status") != "PASS"
        or checkpoint_value.get("state") != "COMPLETE_TASK25"
        or not lock.is_file()
        or (PROFILE / "gateway.pid").exists()
        or not no_profile_process()
    ):
        raise RuntimeError("Task25 stale-lock finalization baseline is unavailable")
    info = lock.lstat()
    if lock.is_symlink() or info.st_uid != os.getuid() or stat.S_IMODE(info.st_mode) != 0o600:
        raise RuntimeError("Task25 stale-lock finalization authority is unsafe")
    bound = {
        "prior_terminal_sha256": sha(TERMINAL),
        "checkpoint_sha256": sha(CHECKPOINT),
        "other_profile_tree_sha256": tree_digest(OTHER),
        "controller_sha256": sha(Path(__file__)),
    }
    return bound, hashlib.sha256(json.dumps(bound, sort_keys=True, separators=(",", ":")).encode()).hexdigest()


def finalize_stale_lock() -> int:
    bound, expected = finalization_baseline()
    if os.environ.get("TASK25_CLEANUP_APPROVAL") != APPROVAL or os.environ.get("TASK25_CLEANUP_FINALIZE_SEAL") != expected:
        raise RuntimeError("Task25 stale-lock finalization permission seal is missing or stale")
    removed = clear_stale_gateway_lock()
    if removed != 1 or (PROFILE / "gateway.lock").exists() or not no_profile_process():
        raise RuntimeError("Task25 stale-lock finalization did not remove exactly one orphan")
    result = load(TERMINAL, {})
    actions = result.get("actions")
    if not isinstance(actions, dict):
        raise RuntimeError("Task25 terminal evidence is malformed")
    actions["stale_gateway_authorities_removed"] = int(actions.get("stale_gateway_authorities_removed", 0)) + removed
    result["post_terminal_stale_lock_reconciliation"] = {"permission_seal": expected, "binding": bound, "removed_gateway_lock_count": removed, "additional_restart_count": 0, "reconciled_at_utc": dt.datetime.now(dt.timezone.utc).isoformat().replace("+00:00", "Z")}
    atomic(TERMINAL, result)
    checkpoint("COMPLETE_TASK25", stale_gateway_lock_reconciled=True)
    print("TASK25_STALE_LOCK_RECONCILIATION_PASS", flush=True)
    return 0


def main() -> int:
    parser = argparse.ArgumentParser()
    choices = parser.add_mutually_exclusive_group(required=True)
    choices.add_argument("--seal", action="store_true")
    choices.add_argument("--run", action="store_true")
    choices.add_argument("--resume-seal", action="store_true")
    choices.add_argument("--resume", action="store_true")
    choices.add_argument("--finalize-seal", action="store_true")
    choices.add_argument("--finalize", action="store_true")
    args = parser.parse_args()
    if args.seal:
        _bound, seal = baseline()
        print(seal)
        return 0
    if args.resume_seal:
        _bound, seal = partial_baseline()
        print(seal)
        return 0
    if args.finalize_seal:
        _bound, seal = finalization_baseline()
        print(seal)
        return 0
    if args.resume:
        return resume()
    if args.finalize:
        return finalize_stale_lock()
    return run()


if __name__ == "__main__":
    raise SystemExit(main())
