#!/bin/sh
set -eu
umask 022

gate_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
root=$(CDPATH= cd -- "$gate_dir/../../../.." && pwd -P)
input=$gate_dir/P15-027-input.json
freebsd_src=${FREEBSD_SRC:-/work/build/freebsd-src}
base=
output=
deadline=120

while test "$#" -gt 0; do
	case "$1" in
	--base)
		test "$#" -ge 2 || { printf '%s\n' '--base requires a commit' >&2; exit 20; }
		base=$2
		shift 2
		;;
	--freebsd-src)
		test "$#" -ge 2 || { printf '%s\n' '--freebsd-src requires a directory' >&2; exit 20; }
		freebsd_src=$2
		shift 2
		;;
	--output)
		test "$#" -ge 2 || { printf '%s\n' '--output requires a directory' >&2; exit 20; }
		output=$2
		shift 2
		;;
	*)
		printf 'unknown argument: %s\n' "$1" >&2
		exit 20
		;;
	esac
done

test -n "$base" || { printf '%s\n' '--base is required' >&2; exit 20; }
test -n "$output" || { printf '%s\n' '--output is required' >&2; exit 20; }
test -f "$input" || { printf 'missing input: %s\n' "$input" >&2; exit 20; }
for tool in date git mktemp patch python3 sha256sum timeout; do
	command -v "$tool" >/dev/null 2>&1 || {
		printf 'missing required host tool: %s\n' "$tool" >&2
		exit 21
	}
done
case "$output" in
/*) ;;
*) output=$PWD/$output ;;
esac
case "$freebsd_src" in
/*) ;;
*) freebsd_src=$PWD/$freebsd_src ;;
esac
test ! -e "$output" || { printf 'refusing existing output: %s\n' "$output" >&2; exit 20; }
mkdir -p "$output"
work=$(mktemp -d "${TMPDIR:-/tmp}/P15-027.XXXXXX")

cleanup_trap()
{
	rm -rf -- "$work"
}
trap cleanup_trap EXIT HUP INT TERM

python3 -B - "$output/command-argv.json" "$0" --base "$base" \
    --freebsd-src "$freebsd_src" --output "$output" <<'PY'
import json
from pathlib import Path
import sys

Path(sys.argv[1]).write_text(
    json.dumps(sys.argv[2:], ensure_ascii=True, separators=(",", ":")) + "\n",
    encoding="ascii",
)
PY
python3 -B - "$output/ownership.json" "$work" "$output" <<'PY'
import json
from pathlib import Path
import sys

Path(sys.argv[1]).write_text(
    json.dumps(
        {
            "owned_temporary_paths": [sys.argv[2]],
            "persistent_output": sys.argv[3],
            "owned_processes": [],
            "owned_ports": [],
            "qemu": "NOT_RUN",
            "protected_resources_addressed": False,
        },
        ensure_ascii=True,
        indent=2,
        sort_keys=True,
    ) + "\n",
    encoding="ascii",
)
PY

set +e
timeout -k 5 "$deadline" python3 -B - \
    "$root" "$input" "$base" "$freebsd_src" "$output" "$work" "$deadline" <<'PY' \
    >"$output/stdout.log" 2>"$output/stderr.log"
from __future__ import annotations

import hashlib
import json
import os
from pathlib import Path
import platform
import re
import shutil
import subprocess
import sys
import tarfile
from typing import Any


ROOT = Path(sys.argv[1])
INPUT = Path(sys.argv[2])
REQUESTED_BASE = sys.argv[3]
FREEBSD_SRC = Path(sys.argv[4])
OUTPUT = Path(sys.argv[5])
WORK = Path(sys.argv[6])
DEADLINE = int(sys.argv[7])
SPEC = json.loads(INPUT.read_text(encoding="utf-8"))


class GateFailure(RuntimeError):
    def __init__(self, status: str, reason: str):
        super().__init__(reason)
        self.status = status
        self.reason = reason


def sha256_bytes(data: bytes) -> str:
    return hashlib.sha256(data).hexdigest()


def sha256_path(path: Path) -> str:
    return sha256_bytes(path.read_bytes())


def write_json(path: Path, value: Any) -> None:
    path.write_text(
        json.dumps(value, ensure_ascii=True, indent=2, sort_keys=True) + "\n",
        encoding="ascii",
    )


def run(
    argv: list[str],
    *,
    cwd: Path | None = None,
    input_bytes: bytes | None = None,
    allowed: set[int] | None = None,
    timeout_seconds: int = 30,
) -> subprocess.CompletedProcess[bytes]:
    try:
        completed = subprocess.run(
            argv,
            cwd=cwd,
            check=False,
            input=input_bytes,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            timeout=timeout_seconds,
        )
    except subprocess.TimeoutExpired as error:
        raise GateFailure(
            "INFRA_BLOCKED", f"command timed out: {' '.join(argv)}"
        ) from error
    accepted = {0} if allowed is None else allowed
    if completed.returncode not in accepted:
        detail = completed.stderr.decode("utf-8", errors="replace").strip()
        raise GateFailure(
            "RUNNER_FAIL",
            f"command failed ({completed.returncode}): {' '.join(argv)}: {detail}",
        )
    return completed


def git_text(repository: Path, *args: str) -> str:
    return run(["git", "-C", str(repository), *args]).stdout.decode(
        "utf-8", errors="strict"
    ).strip()


def source_at(commit: str, relative: str) -> bytes:
    return run(
        ["git", "-C", str(ROOT), "show", f"{commit}:{relative}"]
    ).stdout


def safe_relative_path(value: str) -> Path:
    path = Path(value)
    if path.is_absolute() or ".." in path.parts:
        raise GateFailure("RUNNER_FAIL", f"unsafe declared path: {value}")
    if path.name == "introduction.md":
        raise GateFailure("RUNNER_FAIL", "prohibited path declaration")
    return path


def validate_hash(value: Any, label: str) -> str:
    if not isinstance(value, str) or re.fullmatch(r"[0-9a-f]{64}", value) is None:
        raise GateFailure("RUNNER_FAIL", f"invalid SHA-256 for {label}")
    return value


def validate_runtime_item(item: Any, item_id: str) -> None:
    if not isinstance(item, dict):
        raise GateFailure("RUNNER_FAIL", f"runtime item is not an object: {item_id}")
    expected = {
        "status": "PASS",
        "exit_code": 0,
        "target_marker": "reached",
        "cleanup": "PASS",
    }
    for key, value in expected.items():
        if item.get(key) != value:
            raise GateFailure("RUNNER_FAIL", f"runtime item {item_id} has invalid {key}")
    argv = item.get("command_argv")
    if not isinstance(argv, list) or not argv or not all(isinstance(v, str) for v in argv):
        raise GateFailure("RUNNER_FAIL", f"runtime item {item_id} lacks exact argv")
    if not isinstance(item.get("deadline_seconds"), int) or item["deadline_seconds"] <= 0:
        raise GateFailure("RUNNER_FAIL", f"runtime item {item_id} lacks deadline")
    for stream in ("stdout", "stderr"):
        relative = safe_relative_path(item.get(stream, ""))
        evidence_path = OUTPUT / relative
        if not evidence_path.is_file():
            raise GateFailure("RUNNER_FAIL", f"runtime item {item_id} lacks {stream}")
        expected_hash = validate_hash(item.get(f"{stream}_sha256"), f"{item_id} {stream}")
        if sha256_path(evidence_path) != expected_hash:
            raise GateFailure("RUNNER_FAIL", f"runtime item {item_id} {stream} hash mismatch")


def validate_runtime_record(
    path: Path,
    architecture: dict[str, Any],
    modules: dict[str, dict[str, Any]],
    resolved_base: str,
    patch_sha256: str,
) -> dict[str, Any]:
    record = json.loads(path.read_text(encoding="utf-8"))
    expected_identity = {
        "schema": 1,
        "architecture": architecture["id"],
        "uname_s": "FreeBSD",
        "uname_m": architecture["expected_uname_m"],
        "uname_p": architecture["expected_uname_p"],
        "dut_base": resolved_base,
        "temporary_patch_sha256": patch_sha256,
        "freebsd_source_head": SPEC["freebsd_source"]["head"],
    }
    for key, value in expected_identity.items():
        if record.get(key) != value:
            raise GateFailure("RUNNER_FAIL", f"native record identity mismatch: {key}")
    if record.get("status") not in {"PASS", "DUT_FAIL"}:
        raise GateFailure("RUNNER_FAIL", "native record status is not authoritative")
    if record.get("cleanup") != "PASS" or record.get("target_marker") != "reached":
        raise GateFailure("RUNNER_FAIL", "native record did not reach target with cleanup")
    if record.get("module_sha256") != {
        name: value["sha256"] for name, value in modules.items()
    }:
        raise GateFailure("RUNNER_FAIL", "native module hashes differ from cross artifacts")
    fixtures = record.get("fixture_sha256")
    if not isinstance(fixtures, list) or len(fixtures) < 4:
        raise GateFailure("RUNNER_FAIL", "native record lacks four fixture hashes")
    for index, value in enumerate(fixtures):
        validate_hash(value, f"native fixture {index}")
    capability = record.get("kernel_zstdio")
    validate_runtime_item(capability, "kernel-zstdio-capability")
    if capability.get("options_zstdio") is not True:
        raise GateFailure("RUNNER_FAIL", "native ZSTDIO capability is not enabled")
    operations = record.get("operations")
    if not isinstance(operations, dict):
        raise GateFailure("RUNNER_FAIL", "native operations are absent")
    required = SPEC["native_runtime_contract"]["required_operations"]
    if set(operations) != set(required):
        raise GateFailure("RUNNER_FAIL", "native operation set is not exact")
    for item_id in required:
        validate_runtime_item(operations[item_id], item_id)
    disabled = operations["zstdio0-zstd-read"]
    if disabled.get("errno") != "EOPNOTSUPP":
        raise GateFailure("RUNNER_FAIL", "disabled native Zstd errno is not EOPNOTSUPP")
    return record


def extract_repo_source(resolved_base: str, destination: Path) -> None:
    archive = run(
        [
            "git", "-C", str(ROOT), "archive", "--format=tar", resolved_base,
            "repo-pre-15/src", "repo-pre-15/tests/pre15/probes/ondisk_layout.c",
        ],
        timeout_seconds=60,
    ).stdout
    destination.mkdir(parents=True)
    archive_path = WORK / "repo-source.tar"
    archive_path.write_bytes(archive)
    with tarfile.open(archive_path, mode="r:") as tar:
        tar.extractall(destination, filter="data")


def compile_architecture(
    architecture: dict[str, Any],
    resolved_base: str,
    patch_bytes: bytes,
    compiler: Path,
) -> dict[str, Any]:
    arch_id = architecture["id"]
    arch_root = WORK / "cross" / arch_id
    source_root = arch_root / "source"
    extract_repo_source(resolved_base, source_root)
    run(["patch", "-p1"], cwd=source_root, input_bytes=patch_bytes)
    src = source_root / "repo-pre-15/src"
    sys_root = FREEBSD_SRC / "sys"
    resource_include = Path(
        run([str(compiler), "-print-resource-dir"]).stdout.decode("ascii").strip()
    ) / "include"
    common_flags = [
        "-O2", "-pipe", "-fno-common", "-fno-strict-aliasing", "-D_KERNEL",
        "-DKLD_MODULE", "-nostdinc", "-ffreestanding", "-fwrapv",
        "-fno-asynchronous-unwind-tables", "-fno-omit-frame-pointer",
        "-fstack-protector", "-Wall", "-Wstrict-prototypes",
        "-Wmissing-prototypes", "-Wpointer-arith", "-Wcast-qual", "-Wundef",
        "-Wno-pointer-sign", "-Wmissing-include-dirs", "-Wno-unknown-pragmas",
        "-Wno-address-of-packed-member", "-Wno-format-zero-length", "-std=gnu17",
        "-D__printf__=__freebsd_kprintf__", f"--target={architecture['target_triple']}",
        *architecture["kernel_cflags"],
    ]
    modules: dict[str, dict[str, Any]] = {}
    for zstdio in (0, 1):
        build = arch_root / f"zstdio{zstdio}"
        build.mkdir(parents=True)
        (build / "opt_global.h").write_bytes(b"")
        (build / "machine").symlink_to(sys_root / architecture["machine_header_dir"] / "include")
        for alias, relative in architecture["header_aliases"].items():
            (build / alias).symlink_to(sys_root / relative)
        for mode in ("-p", "-q", "-h"):
            generated = run(
                ["awk", "-f", str(sys_root / "tools/vnode_if.awk"),
                 str(sys_root / "kern/vnode_if.src"), mode],
                cwd=build,
            ).stdout
            suffix = {"-p": "vnode_if_newproto.h", "-q": "vnode_if_typedef.h", "-h": "vnode_if.h"}[mode]
            (build / suffix).write_bytes(generated)
        include_flags = [
            "-include", str(build / "opt_global.h"), "-I", str(build),
            "-I", str(sys_root), "-I", str(sys_root / "contrib/ck/include"),
        ]
        objects = []
        stdout_parts = []
        stderr_parts = []
        for source_name in SPEC["cross_build_contract"]["module_sources"]:
            obj = build / f"{Path(source_name).stem}.o"
            argv = [str(compiler), *common_flags, *include_flags]
            if source_name == "decompressor_zstd.c":
                argv.extend(["-I", str(sys_root / "contrib/zstd/lib/freebsd")])
                if zstdio == 1:
                    argv.append("-DZSTDIO")
            argv.extend(["-c", str(src / source_name), "-o", str(obj)])
            completed = run(argv, cwd=build, timeout_seconds=60)
            stdout_parts.append(completed.stdout)
            stderr_parts.append(completed.stderr)
            objects.append(obj)
        module = build / "erofs.ko"
        linked = run(
            [str(compiler), f"--target={architecture['target_triple']}",
             "-r", "-nostdlib", *map(str, objects), "-o", str(module)],
            cwd=build,
            timeout_seconds=60,
        )
        stdout_parts.append(linked.stdout)
        stderr_parts.append(linked.stderr)
        nm_output = run(["nm", "-u", str(module)]).stdout
        (build / "build.stdout").write_bytes(b"".join(stdout_parts))
        (build / "build.stderr").write_bytes(b"".join(stderr_parts))
        (build / "nm-u.txt").write_bytes(nm_output)
        modules[f"zstdio{zstdio}"] = {
            "path": str(module),
            "sha256": sha256_path(module),
            "size_bytes": module.stat().st_size,
            "nm_u_sha256": sha256_bytes(nm_output),
        }

    probe_root = arch_root / "probes"
    probe_root.mkdir()
    include_root = probe_root / "include"
    include_root.mkdir()
    (include_root / "machine").symlink_to(
        sys_root / architecture["machine_header_dir"] / "include"
    )
    for alias, relative in architecture["header_aliases"].items():
        (include_root / alias).symlink_to(sys_root / relative)
    probe_flags = [
        f"--target={architecture['target_triple']}", "-std=gnu17", "-nostdinc",
        "-isystem", str(resource_include), "-isystem", str(FREEBSD_SRC / "include"),
        "-isystem", str(include_root), "-isystem", str(sys_root),
    ]
    layout = source_root / "repo-pre-15/tests/pre15/probes/ondisk_layout.c"
    layout_result = run(
        [str(compiler), *probe_flags, "-Wall", "-Wextra", "-Werror",
         "-fsyntax-only", "-Xclang", "-fdump-record-layouts", str(layout)],
        timeout_seconds=60,
    )
    (probe_root / "layout.stdout").write_bytes(layout_result.stdout)
    (probe_root / "layout.stderr").write_bytes(layout_result.stderr)
    unaligned = probe_root / "unaligned-endian.c"
    unaligned.write_text(
        SPEC["cross_build_contract"]["unaligned_endian_probe_source"],
        encoding="ascii",
    )
    assembly = probe_root / "unaligned-endian.s"
    endian_result = run(
        [str(compiler), *probe_flags, *architecture["kernel_cflags"],
         "-O2", "-S", str(unaligned), "-o", str(assembly)],
        timeout_seconds=60,
    )
    (probe_root / "unaligned-endian.stdout").write_bytes(endian_result.stdout)
    (probe_root / "unaligned-endian.stderr").write_bytes(endian_result.stderr)
    if assembly.stat().st_size == 0:
        raise GateFailure("RUNNER_FAIL", f"empty unaligned/endian probe for {arch_id}")
    return {
        "status": "PASS",
        "temporary_source": str(source_root),
        "modules": modules,
        "layout_probe_sha256": sha256_path(layout),
        "layout_output_sha256": sha256_bytes(layout_result.stdout),
        "unaligned_endian_probe_sha256": sha256_path(unaligned),
        "unaligned_endian_assembly_sha256": sha256_path(assembly),
    }


def render_argv(values: list[str], substitutions: dict[str, str]) -> list[str]:
    rendered = []
    for value in values:
        for key, replacement in substitutions.items():
            value = value.replace("{" + key + "}", replacement)
        rendered.append(value)
    return rendered


def run_native(
    architecture: dict[str, Any],
    declaration: dict[str, Any],
    modules: dict[str, dict[str, Any]],
    resolved_base: str,
    patch_sha256: str,
) -> dict[str, Any]:
    runner_relative = safe_relative_path(declaration.get("runner_path", ""))
    runner = ROOT / runner_relative
    if not runner.is_file():
        raise GateFailure("INFRA_BLOCKED", f"declared native runner is absent: {runner_relative}")
    if sha256_path(runner) != validate_hash(
        declaration.get("runner_sha256"), f"{architecture['id']} runner"
    ):
        raise GateFailure("INFRA_BLOCKED", "declared native runner identity changed")
    native_output = OUTPUT / "native" / architecture["id"]
    native_output.mkdir(parents=True)
    substitutions = {
        "runner": str(runner),
        "architecture": architecture["id"],
        "module_zstdio0": modules["zstdio0"]["path"],
        "module_zstdio1": modules["zstdio1"]["path"],
        "output": str(native_output),
    }
    preflight_argv = render_argv(declaration["preflight_argv"], substitutions)
    preflight = run(
        preflight_argv,
        cwd=ROOT,
        timeout_seconds=declaration["preflight_deadline_seconds"],
    )
    (native_output / "preflight.runner.stdout").write_bytes(preflight.stdout)
    (native_output / "preflight.runner.stderr").write_bytes(preflight.stderr)
    preflight_record = json.loads(
        (native_output / "preflight.json").read_text(encoding="utf-8")
    )
    for key, value in {
        "status": "PASS", "exit_code": 0, "target_marker": "reached",
        "cleanup": "PASS", "uname_s": "FreeBSD",
        "uname_m": architecture["expected_uname_m"],
        "uname_p": architecture["expected_uname_p"],
    }.items():
        if preflight_record.get(key) != value:
            raise GateFailure("INFRA_BLOCKED", f"native preflight mismatch: {key}")
    runtime_argv = render_argv(declaration["runtime_argv"], substitutions)
    runtime = run(
        runtime_argv,
        cwd=ROOT,
        allowed={0, 10},
        timeout_seconds=declaration["runtime_deadline_seconds"],
    )
    (native_output / "runner.stdout").write_bytes(runtime.stdout)
    (native_output / "runner.stderr").write_bytes(runtime.stderr)
    return validate_runtime_record(
        native_output / "runtime-result.json",
        architecture,
        modules,
        resolved_base,
        patch_sha256,
    )


def main() -> int:
    if SPEC.get("schema") != 1 or SPEC.get("candidate") != "P15-027":
        raise GateFailure("RUNNER_FAIL", "invalid P15-027 input identity")
    if SPEC.get("gate") != "G07" or SPEC.get("batch") != "B36":
        raise GateFailure("RUNNER_FAIL", "invalid G07/B36 input identity")
    if SPEC.get("prohibited_paths") != ["introduction.md"]:
        raise GateFailure("RUNNER_FAIL", "prohibited-path contract changed")
    resolved = git_text(ROOT, "rev-parse", f"{REQUESTED_BASE}^{{commit}}")
    if resolved != SPEC["required_base"]:
        raise GateFailure(
            "INFRA_BLOCKED", f"P15-027 must replay {SPEC['required_base']}, got {resolved}"
        )
    source_tree = git_text(ROOT, "rev-parse", f"{resolved}:repo-pre-15/src")
    if source_tree != SPEC["repo_source_tree_oid"]:
        raise GateFailure("INFRA_BLOCKED", "frozen EROFS source tree changed")
    source_hashes = {
        path: sha256_bytes(source_at(resolved, path))
        for path in SPEC["source_sha256"]
    }
    if source_hashes != SPEC["source_sha256"]:
        raise GateFailure("INFRA_BLOCKED", "frozen gate source identity changed")
    write_json(OUTPUT / "source-sha256.json", source_hashes)

    addendum_paths = (
        "repo-pre-15/tests/pre15/gates/P15-027.sh",
        "repo-pre-15/tests/pre15/gates/P15-027-input.json",
        "repo-pre-15/docs/pre15-stage0/P15-027.md",
    )
    addendum_hashes = {
        path: sha256_path(ROOT / path) for path in addendum_paths
    }
    write_json(OUTPUT / "gate-addendum-sha256.json", addendum_hashes)
    if sha256_path(ROOT / "repo-pre-15/src/Makefile") != SPEC["source_sha256"]["repo-pre-15/src/Makefile"]:
        raise GateFailure("RUNNER_FAIL", "production Makefile differs from frozen BASE")

    patch_spec = SPEC["temporary_makefile_relaxation"]
    patch_bytes = patch_spec["unified_diff"].encode("ascii")
    if sha256_bytes(patch_bytes) != patch_spec["sha256"]:
        raise GateFailure("RUNNER_FAIL", "input-recorded temporary patch hash mismatch")
    patch_check = WORK / "patch-check"
    makefile_copy = patch_check / "repo-pre-15/src/Makefile"
    makefile_copy.parent.mkdir(parents=True)
    makefile_copy.write_bytes(source_at(resolved, patch_spec["path"]))
    patch_result = run(["patch", "-p1"], cwd=patch_check, input_bytes=patch_bytes)
    (OUTPUT / "makefile-relaxation.patch").write_bytes(patch_bytes)
    (OUTPUT / "patch.stdout").write_bytes(patch_result.stdout)
    (OUTPUT / "patch.stderr").write_bytes(patch_result.stderr)
    if sha256_path(makefile_copy) != patch_spec["patched_makefile_sha256"]:
        raise GateFailure("RUNNER_FAIL", "temporary Makefile relaxation result changed")
    patch_record = {
        "path": patch_spec["path"],
        "sha256": patch_spec["sha256"],
        "patched_makefile_sha256": sha256_path(makefile_copy),
        "production_makefile_changed": False,
        "temporary_apply": "PASS",
    }
    write_json(OUTPUT / "temporary-patch.json", patch_record)

    if not FREEBSD_SRC.is_dir():
        raise GateFailure("INFRA_BLOCKED", f"FreeBSD source is absent: {FREEBSD_SRC}")
    freebsd = SPEC["freebsd_source"]
    freebsd_head = git_text(FREEBSD_SRC, "rev-parse", "HEAD")
    freebsd_prefix = git_text(FREEBSD_SRC, "rev-parse", "--show-prefix")
    if freebsd_head != freebsd["head"] or freebsd_prefix != freebsd["git_prefix"]:
        raise GateFailure("INFRA_BLOCKED", "FreeBSD source identity changed")
    git_root = Path(git_text(FREEBSD_SRC, "rev-parse", "--show-toplevel"))
    freebsd_source_tree = git_text(
        git_root, "rev-parse", f"{freebsd_head}:{freebsd['git_tree_path']}"
    )
    freebsd_sys_tree = git_text(
        git_root, "rev-parse", f"{freebsd_head}:{freebsd['git_tree_path']}/sys"
    )
    if freebsd_source_tree != freebsd["source_tree_oid"] or freebsd_sys_tree != freebsd["sys_tree_oid"]:
        raise GateFailure("INFRA_BLOCKED", "FreeBSD source tree object changed")
    freebsd_hashes = {
        path: sha256_path(FREEBSD_SRC / path) for path in freebsd["sha256"]
    }
    if freebsd_hashes != freebsd["sha256"]:
        raise GateFailure("INFRA_BLOCKED", "selected FreeBSD source hashes changed")

    compiler_path = Path(shutil.which("clang") or "").resolve()
    if not compiler_path.is_file():
        raise GateFailure("INFRA_BLOCKED", "clang is unavailable")
    compiler = SPEC["toolchain"]["compiler"]
    compiler_version = run([str(compiler_path), "--version"]).stdout.decode(
        "utf-8", errors="strict"
    ).splitlines()[0]
    if (
        str(compiler_path) != compiler["realpath"]
        or sha256_path(compiler_path) != compiler["sha256"]
        or compiler_version != compiler["version"]
    ):
        raise GateFailure("INFRA_BLOCKED", "cross compiler identity changed")
    compiler_targets = run([str(compiler_path), "--print-targets"]).stdout.decode(
        "utf-8", errors="strict"
    )

    architectures = SPEC["architectures"]
    if [item.get("id") for item in architectures] != ["arm64", "riscv64", "i386"]:
        raise GateFailure("RUNNER_FAIL", "architecture audit set is not exact")
    if sum(item.get("pointer_bits") == 32 for item in architectures) < 1:
        raise GateFailure("RUNNER_FAIL", "architecture audit lacks a 32-bit target")
    source_support = {}
    for architecture in architectures:
        arch_id = architecture["id"]
        header = FREEBSD_SRC / "sys" / architecture["machine_header_dir"] / "include/param.h"
        if not header.is_file():
            raise GateFailure("INFRA_BLOCKED", f"FreeBSD source lacks {arch_id}")
        if sha256_path(header) != architecture["param_h_sha256"]:
            raise GateFailure("INFRA_BLOCKED", f"FreeBSD {arch_id} source identity changed")
        target_pattern = rf"^\s*{re.escape(architecture['compiler_backend'])}\s+-"
        if re.search(target_pattern, compiler_targets, re.MULTILINE) is None:
            raise GateFailure("INFRA_BLOCKED", f"clang lacks {arch_id} backend")
        source_support[arch_id] = {
            "status": "PASS",
            "freebsd_machine_headers": str(header),
            "param_h_sha256": sha256_path(header),
            "compiler_backend": architecture["compiler_backend"],
            "target_triple": architecture["target_triple"],
            "pointer_bits": architecture["pointer_bits"],
        }

    probe_source = SPEC["cross_build_contract"]["unaligned_endian_probe_source"].encode("ascii")
    if sha256_bytes(probe_source) != SPEC["cross_build_contract"]["unaligned_endian_probe_sha256"]:
        raise GateFailure("RUNNER_FAIL", "input-recorded unaligned/endian probe changed")
    inventory = {
        "schema": 1,
        "host": {"system": platform.system(), "machine": platform.machine()},
        "local_host_is_qualifying_native_freebsd": False,
        "local_host_reason": "host is not FreeBSD and is not any candidate architecture",
        "declared_native_environments": {
            item["id"]: item["native_environment"] is not None for item in architectures
        },
        "emulator_tools": {
            item["id"]: shutil.which(item["emulator_tool"]) for item in architectures
        },
        "emulator_binary_is_native_runtime_evidence": False,
        "source_toolchain_support": source_support,
        "protected_resources_addressed": False,
        "inventory_rule": "only an explicit, validated same-architecture FreeBSD runner declaration can start cross work",
    }
    write_json(OUTPUT / "runtime-environment-inventory.json", inventory)
    write_json(
        OUTPUT / "freebsd-source-identity.json",
        {
            "path": str(FREEBSD_SRC),
            "git_root": str(git_root),
            "git_prefix": freebsd_prefix,
            "git_tree_path": freebsd["git_tree_path"],
            "head": freebsd_head,
            "source_tree_oid": freebsd_source_tree,
            "sys_tree_oid": freebsd_sys_tree,
            "sha256": freebsd_hashes,
        },
    )
    write_json(
        OUTPUT / "toolchain-identity.json",
        {
            "compiler_realpath": str(compiler_path),
            "compiler_sha256": sha256_path(compiler_path),
            "compiler_version": compiler_version,
            "print_targets_sha256": sha256_bytes(compiler_targets.encode("utf-8")),
        },
    )

    results = []
    go_architectures = []
    for architecture in architectures:
        declaration = architecture["native_environment"]
        record: dict[str, Any] = {
            "architecture": architecture["id"],
            "machine_arch": architecture["machine_arch"],
            "pointer_bits": architecture["pointer_bits"],
            "source_toolchain": source_support[architecture["id"]],
        }
        if declaration is None:
            record.update(
                {
                    "native_environment": {
                        "status": "STOP",
                        "reason": "no declared same-architecture FreeBSD runtime environment",
                    },
                    "cross_build_and_probes": {
                        "status": "NOT_RUN",
                        "reason": "cross-only evidence cannot authorize allowlisting",
                    },
                    "native_runtime": {
                        "status": "NOT_RUN",
                        "reason": "same-architecture FreeBSD runtime is absent",
                    },
                    "decision": "STOP",
                }
            )
            results.append(record)
            continue
        for key in (
            "runner_path", "runner_sha256", "preflight_argv", "runtime_argv",
            "preflight_deadline_seconds", "runtime_deadline_seconds",
        ):
            if key not in declaration:
                raise GateFailure("RUNNER_FAIL", f"incomplete native declaration: {key}")
        cross = compile_architecture(
            architecture, resolved, patch_bytes, compiler_path
        )
        native = run_native(
            architecture,
            declaration,
            cross["modules"],
            resolved,
            patch_spec["sha256"],
        )
        native_pass = native["status"] == "PASS"
        record.update(
            {
                "native_environment": {"status": "PASS", "declaration": declaration},
                "cross_build_and_probes": cross,
                "native_runtime": native,
                "decision": "GO" if native_pass else "STOP",
            }
        )
        if native_pass:
            go_architectures.append(architecture["id"])
        results.append(record)

    overall_status = "GO" if go_architectures else "STOP"
    result = {
        "schema": 1,
        "gate": "G07",
        "candidate": "P15-027",
        "batch": "B36",
        "status": overall_status,
        "reason": (
            "at least one architecture completed its own cross and native requirements"
            if go_architectures
            else "no architecture has a declared same-architecture FreeBSD runtime"
        ),
        "requested_base": REQUESTED_BASE,
        "resolved_base": resolved,
        "repo_source_tree_oid": source_tree,
        "deadline_seconds": DEADLINE,
        "expected_exit_code": 0 if go_architectures else 22,
        "architectures": results,
        "go_architectures": go_architectures,
        "allowlist_authorization": go_architectures,
        "false_go_guard": "each authorized architecture must independently have cross_build_and_probes=PASS and native_runtime=PASS",
        "b36": "AUTHORIZED" if go_architectures else "STOP-NO-SOURCE",
        "production_makefile_guard_preserved": True,
        "production_source_changed": False,
        "qemu": "NOT_RUN" if not go_architectures else "runner-defined",
        "full_feature_suite": "NOT_RUN",
        "smoke_suite": "NOT_RUN",
        "protected_resources_addressed": False,
    }
    write_json(OUTPUT / "result.json", result)
    print(json.dumps(result, ensure_ascii=True, sort_keys=True))
    return 0 if go_architectures else 22


try:
    raise SystemExit(main())
except GateFailure as error:
    failure = {
        "schema": 1,
        "gate": "G07",
        "candidate": "P15-027",
        "status": error.status,
        "reason": error.reason,
        "requested_base": REQUESTED_BASE,
        "deadline_seconds": DEADLINE,
        "b36": "NOT_RUN",
        "target_marker": "not_reached",
        "production_source_changed": False,
        "protected_resources_addressed": False,
    }
    write_json(OUTPUT / "result.json", failure)
    print(json.dumps(failure, ensure_ascii=True, sort_keys=True))
    raise SystemExit({"RUNNER_FAIL": 20, "INFRA_BLOCKED": 21}.get(error.status, 20))
PY
gate_rc=$?
set -e

cleanup_status=PASS
if ! rm -rf -- "$work"; then
	cleanup_status=FAIL
	gate_rc=20
fi
trap - EXIT HUP INT TERM
printf 'owned temporary path removed: %s\ncleanup=%s\n' \
    "$work" "$cleanup_status" >"$output/cleanup.log"

python3 -B - "$output" "$gate_rc" "$cleanup_status" <<'PY'
from __future__ import annotations

import hashlib
import json
from pathlib import Path
import sys


output = Path(sys.argv[1])
exit_code = int(sys.argv[2])
cleanup = sys.argv[3]
if cleanup != "PASS":
    status = "RUNNER_FAIL"
    origin = "runner"
elif exit_code == 0:
    status = "PASS"
    origin = "gate"
elif exit_code == 22:
    status = "STOP"
    origin = "gate"
elif exit_code in (124, 137):
    status = "INFRA_BLOCKED"
    origin = "infrastructure"
else:
    status = "RUNNER_FAIL"
    origin = "runner"
(output / "attempt.json").write_text(
    json.dumps(
        {
            "schema": 1,
            "exit_code": exit_code,
            "status": status,
            "failure_origin": origin,
            "cleanup": cleanup,
            "target_marker": "reached" if status in {"PASS", "STOP"} else "not_reached",
        },
        ensure_ascii=True,
        indent=2,
        sort_keys=True,
    ) + "\n",
    encoding="ascii",
)
lines = []
for path in sorted(output.iterdir(), key=lambda item: item.name):
    if path.is_file() and path.name != "SHA256SUMS":
        digest = hashlib.sha256(path.read_bytes()).hexdigest()
        lines.append(f"{digest}  {path.name}")
(output / "SHA256SUMS").write_text("\n".join(lines) + "\n", encoding="ascii")
PY

printf 'P15-027 gate exit=%s cleanup=%s output=%s\n' \
    "$gate_rc" "$cleanup_status" "$output"
exit "$gate_rc"
