#!/usr/bin/env python3
"""
helix_cdc/runtime/golden_verifier.py

WO-ECHO-POLICY-GOLDEN-01 - Golden Verification for Policy Actions

Provides real baseline vs policy comparison to verify that policy actions
don't break correctness. A "PASS" means the policy action produced output
that matches the baseline within the cosine similarity threshold.

Key Invariant:
    For same (seed, prompt, manifest), baseline run and policy run must match:
    cosine(output_policy, output_baseline) >= 0.9999

Usage:
    from helix_cdc.runtime.golden_verifier import verify_policy_correctness
    from helix_cdc.runtime.policy_harness import PolicyAction

    result = verify_policy_correctness(
        X=input_activations,
        manifest_path="seeds/hybrid_manifest_v2_full_cdna2.json",
        block_index=0,
        action=PolicyAction(cpp_kernel=1, fused_matmul=1),
        gguf_path="model.gguf",
    )

    if result.passed:
        print(f"PASS: cosine={result.cosine:.6f}")
    else:
        print(f"FAIL: cosine={result.cosine:.6f}")
"""

from __future__ import annotations

import hashlib
import time
from dataclasses import dataclass, field, asdict
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple, Union

import numpy as np

from helix_cdc.runtime.policy_harness import PolicyAction, PolicyHarness


# =============================================================================
# Helper Functions
# =============================================================================

def sha256_array(arr: np.ndarray) -> str:
    """
    Compute SHA256 hash of numpy array with dtype discipline.

    WO-ECHO-POLICY-GOLDEN-01.1a: Includes dtype + contiguous bytes for consistent hashing.
    """
    # Ensure consistent memory layout (C-contiguous)
    arr_c = np.ascontiguousarray(arr)
    # Include dtype in hash to distinguish e.g. float32 vs float64
    dtype_bytes = str(arr_c.dtype).encode()
    shape_bytes = str(arr_c.shape).encode()
    data_bytes = arr_c.tobytes()
    combined = dtype_bytes + b"|" + shape_bytes + b"|" + data_bytes
    return hashlib.sha256(combined).hexdigest()[:16]


def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
    """
    Compute cosine similarity between two arrays.

    Returns value in [-1, 1], where 1 means identical direction.
    Clamps result to valid range to handle IEEE-754 floating point slop.
    """
    a_flat = a.flatten().astype(np.float64)
    b_flat = b.flatten().astype(np.float64)

    norm_a = np.linalg.norm(a_flat)
    norm_b = np.linalg.norm(b_flat)

    if norm_a < 1e-10 or norm_b < 1e-10:
        return 0.0

    cos = float(np.dot(a_flat, b_flat) / (norm_a * norm_b))
    # Clamp to valid range (floating point slop can exceed 1.0)
    return max(-1.0, min(1.0, cos))


# =============================================================================
# RuntimeSignature - Track which codepath was used
# =============================================================================

@dataclass
class RuntimeSignature:
    """
    Which codepath was actually used during block forward.

    WO-ECHO-POLICY-GOLDEN-01.1: Added to verify knobs actually change codepaths.
    """
    matmul_impl: str = "unknown"  # "cpp_fused" | "cpp_block" | "python" | "unknown"
    verify_policy: str = "unknown"  # "always" | "trust_cached" | "none"
    fibpi_mode: str = "unknown"  # "full" | "bypass"
    cpp_kernel_enabled: bool = False
    fused_matmul_enabled: bool = False

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dict for JSON serialization."""
        return asdict(self)

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, RuntimeSignature):
            return False
        return (
            self.matmul_impl == other.matmul_impl
            and self.verify_policy == other.verify_policy
            and self.fibpi_mode == other.fibpi_mode
            and self.cpp_kernel_enabled == other.cpp_kernel_enabled
            and self.fused_matmul_enabled == other.fused_matmul_enabled
        )

    def mismatch_fields(self, other: "RuntimeSignature") -> List[str]:
        """
        Return list of field names that differ between this signature and other.

        WO-ECHO-POLICY-GOLDEN-01.1a: For debugging req vs obs mismatches.
        """
        if not isinstance(other, RuntimeSignature):
            return ["invalid_comparison"]

        mismatches = []
        if self.matmul_impl != other.matmul_impl:
            mismatches.append("matmul_impl")
        if self.verify_policy != other.verify_policy:
            mismatches.append("verify_policy")
        if self.fibpi_mode != other.fibpi_mode:
            mismatches.append("fibpi_mode")
        if self.cpp_kernel_enabled != other.cpp_kernel_enabled:
            mismatches.append("cpp_kernel_enabled")
        if self.fused_matmul_enabled != other.fused_matmul_enabled:
            mismatches.append("fused_matmul_enabled")
        return mismatches


def extract_requested_signature(action: PolicyAction) -> RuntimeSignature:
    """
    Extract REQUESTED RuntimeSignature from action and environment.

    WO-ECHO-POLICY-GOLDEN-01.1a: This is what we *asked* for, not what actually happened.
    Use extract_observed_signature() to get the truth from receipts.
    """
    import os

    cpp_kernel = os.environ.get("HELIX_USE_CPP_KERNEL", "0") == "1" or action.cpp_kernel == 1
    fused_matmul = os.environ.get("HELIX_USE_FUSED_MATMUL", "0") == "1" or action.fused_matmul == 1

    # Determine matmul implementation
    if cpp_kernel and fused_matmul:
        matmul_impl = "cpp_fused"
    elif cpp_kernel:
        matmul_impl = "cpp_block"
    else:
        matmul_impl = "python"

    return RuntimeSignature(
        matmul_impl=matmul_impl,
        verify_policy=action.verify_policy_str,
        fibpi_mode=action.fibpi_mode_str,
        cpp_kernel_enabled=cpp_kernel,
        fused_matmul_enabled=fused_matmul,
    )


def _extract_native_kernel_from_projection(proj_receipt: Dict[str, Any]) -> Optional[Dict[str, Any]]:
    """Extract native_kernel info from a projection receipt (q/k/v/o)."""
    if not proj_receipt:
        return None
    # Try both key names for resilience
    return proj_receipt.get("native_kernel") or proj_receipt.get("native_kernel_info")


def extract_observed_signature(receipt: Dict[str, Any]) -> RuntimeSignature:
    """
    Extract OBSERVED RuntimeSignature from execution receipt.

    WO-ECHO-POLICY-GOLDEN-01.1a: This is what *actually* happened, extracted from
    native_kernel_info in StreamXWReceipt (via AttentionLayerReceipt).

    Resilient extraction:
    - Checks q/k/v/o_receipt for native_kernel
    - Checks top-level native_kernel_info
    - Handles conflicts by marking matmul_impl="conflict"

    The truth comes from the receipt, not from what we asked for.
    """
    # Collect native_kernel from multiple sources for resilience
    sources = []

    # Try attention_receipt projections (q/k/v/o)
    attn_receipt = receipt.get("attention_receipt") or {}
    for proj_name in ["q_receipt", "k_receipt", "v_receipt", "o_receipt"]:
        proj = attn_receipt.get(proj_name) or {}
        nk = _extract_native_kernel_from_projection(proj)
        if nk:
            sources.append((f"attn.{proj_name}", nk))

    # Try FFN receipt projections
    ffn_receipt = receipt.get("ffn_receipt") or {}
    for proj_name in ["gate_receipt", "up_receipt", "down_receipt"]:
        proj = ffn_receipt.get(proj_name) or {}
        nk = _extract_native_kernel_from_projection(proj)
        if nk:
            sources.append((f"ffn.{proj_name}", nk))

    # Try top-level native_kernel_info
    top_level_nk = receipt.get("native_kernel_info") or receipt.get("native_kernel")
    if top_level_nk:
        sources.append(("top_level", top_level_nk))

    # WO-ECHO-POLICY-GOLDEN-BITE-01: Try new receipt structure
    # Path: receipt['components']['attention']['projections']['q']['native_kernel']
    components = receipt.get("components") or {}
    for comp_name, proj_names in [
        ("attention", ["q", "k", "v", "o"]),
        ("ffn", ["gate", "up", "down"]),
    ]:
        comp = components.get(comp_name) or {}
        projections = comp.get("projections") or {}
        for proj_name in proj_names:
            proj = projections.get(proj_name) or {}
            nk = _extract_native_kernel_from_projection(proj)
            if nk:
                sources.append((f"components.{comp_name}.{proj_name}", nk))

    # If no sources found, return unknown
    if not sources:
        block_config = receipt.get("block_config") or {}
        return RuntimeSignature(
            matmul_impl="unknown",
            verify_policy=block_config.get("verify_policy", "unknown"),
            fibpi_mode="unknown",
            cpp_kernel_enabled=False,
            fused_matmul_enabled=False,
        )

    # Extract kernel path from first available source
    # Check for conflicts across sources
    matmul_impls = set()
    for source_name, nk in sources:
        # Handle both key names: "used" or "enabled"
        cpp_used = nk.get("used", nk.get("enabled", False))
        fused_used = nk.get("fused_matmul_used", nk.get("fused_matmul_enabled", False))

        if fused_used:
            impl = "cpp_fused"
        elif cpp_used:
            impl = "cpp_block"
        else:
            impl = "python"
        matmul_impls.add(impl)

    # Use first source for values, but mark conflict if sources disagree
    first_nk = sources[0][1]
    cpp_used = first_nk.get("used", first_nk.get("enabled", False))
    fused_used = first_nk.get("fused_matmul_used", first_nk.get("fused_matmul_enabled", False))

    if len(matmul_impls) > 1:
        matmul_impl = "conflict"  # Different projections used different paths!
    elif fused_used:
        matmul_impl = "cpp_fused"
    elif cpp_used:
        matmul_impl = "cpp_block"
    else:
        matmul_impl = "python"

    # Get verify_policy from block config if available
    block_config = receipt.get("block_config") or {}
    verify_policy = block_config.get("verify_policy", "unknown")

    # fibpi_mode - check if recorded anywhere
    fibpi_mode = block_config.get("fibpi_mode", "unknown")

    return RuntimeSignature(
        matmul_impl=matmul_impl,
        verify_policy=verify_policy,
        fibpi_mode=fibpi_mode,
        cpp_kernel_enabled=cpp_used,
        fused_matmul_enabled=fused_used,
    )


# Backwards compatibility alias
extract_runtime_signature = extract_requested_signature


# =============================================================================
# GoldenVerificationResult
# =============================================================================

@dataclass
class GoldenVerificationResult:
    """
    Result of baseline vs policy comparison.

    Contains hashes, cosine similarity, timing, and pass/fail status.

    WO-ECHO-POLICY-GOLDEN-01.1: Added runtime signatures and bitwise identity.
    WO-ECHO-POLICY-GOLDEN-01.1a: Split into requested vs observed signatures.
    """
    # Hashes for audit trail
    baseline_hash: str = ""
    policy_hash: str = ""

    # Similarity metrics
    cosine: float = 0.0
    max_abs_error: float = 0.0

    # WO-ECHO-POLICY-GOLDEN-01.1: Bitwise identity check
    bitwise_identical: bool = False  # True = SHA256 of outputs match exactly

    # Pass/fail
    passed: bool = False
    threshold: float = 0.9999

    # Timing
    baseline_duration_ms: float = 0.0
    policy_duration_ms: float = 0.0

    # Action used
    action_used: Dict[str, Any] = field(default_factory=dict)
    action_index: int = -1

    # WO-ECHO-POLICY-GOLDEN-01.1a: Requested signatures (what we asked for)
    baseline_requested_signature: Optional[RuntimeSignature] = None
    policy_requested_signature: Optional[RuntimeSignature] = None

    # WO-ECHO-POLICY-GOLDEN-01.1a: Observed signatures (what actually happened, from receipts)
    baseline_observed_signature: Optional[RuntimeSignature] = None
    policy_observed_signature: Optional[RuntimeSignature] = None

    # WO-ECHO-POLICY-GOLDEN-01.1a: Signature comparison flags
    signatures_differ: bool = False  # True = observed_baseline != observed_policy
    baseline_req_vs_obs_mismatch: bool = False  # True = baseline asked != baseline got
    policy_req_vs_obs_mismatch: bool = False  # True = policy asked != policy got

    # WO-ECHO-POLICY-GOLDEN-01.1a: Mismatch field tracking for debugging
    baseline_mismatch_fields: List[str] = field(default_factory=list)  # Which fields differ req vs obs
    policy_mismatch_fields: List[str] = field(default_factory=list)  # Which fields differ req vs obs

    # Backwards compat aliases (deprecated, use *_requested_signature)
    baseline_signature: Optional[RuntimeSignature] = None
    policy_signature: Optional[RuntimeSignature] = None

    # Context
    block_index: int = 0
    input_shape: List[int] = field(default_factory=list)
    output_shape: List[int] = field(default_factory=list)

    # Metadata
    timestamp: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"))
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dict for JSON serialization."""
        d = asdict(self)
        # Convert RuntimeSignature to dict if present
        for key in ["baseline_requested_signature", "policy_requested_signature",
                    "baseline_observed_signature", "policy_observed_signature",
                    "baseline_signature", "policy_signature"]:
            sig = getattr(self, key, None)
            if sig:
                d[key] = sig.to_dict()
        return d


# =============================================================================
# Core Verification Function
# =============================================================================

def verify_policy_correctness(
    X: np.ndarray,
    manifest_path: Union[str, Path],
    block_index: int,
    action: PolicyAction,
    gguf_path: Optional[Union[str, Path]] = None,
    d_head: int = 128,
    threshold: float = 0.9999,
    harness: Optional[PolicyHarness] = None,
) -> GoldenVerificationResult:
    """
    Run block forward twice: baseline vs policy. Compare outputs.

    This is the core verification function that proves policy actions
    don't break correctness.

    Args:
        X: Input activations [batch, seq, d_model] or [seq, d_model]
        manifest_path: Path to CDNA manifest
        block_index: Transformer block index
        action: Policy action to verify
        gguf_path: Path to GGUF file for norm weights
        d_head: Head dimension for attention
        threshold: Minimum cosine similarity for PASS (default: 0.9999)
        harness: Optional PolicyHarness (created if not provided)

    Returns:
        GoldenVerificationResult with comparison results
    """
    from helix_cdc.regrow.stream_transformer_block import stream_transformer_block_forward

    if harness is None:
        harness = PolicyHarness.default()

    result = GoldenVerificationResult(
        threshold=threshold,
        block_index=block_index,
        input_shape=list(X.shape),
        action_used=action.to_dict(),
        action_index=action.to_index(),
    )

    try:
        # Run 1: Baseline (default action, trust_cached for speed)
        baseline_action = PolicyAction.baseline()

        # WO-ECHO-POLICY-GOLDEN-01.1a: Extract REQUESTED signature before run
        result.baseline_requested_signature = extract_requested_signature(baseline_action)
        result.baseline_signature = result.baseline_requested_signature  # Backwards compat

        t0 = time.perf_counter()

        with harness.apply_action(baseline_action):
            baseline_output, baseline_receipt, _ = stream_transformer_block_forward(
                X=X,
                manifest_path=manifest_path,
                block_index=block_index,
                d_head=d_head,
                verify_policy=baseline_action.verify_policy_str,
                gguf_path=gguf_path,
            )

        result.baseline_duration_ms = (time.perf_counter() - t0) * 1000
        result.baseline_hash = sha256_array(baseline_output)

        # WO-ECHO-POLICY-GOLDEN-01.1a: Extract OBSERVED signature from receipt
        baseline_receipt_dict = baseline_receipt.to_dict() if hasattr(baseline_receipt, 'to_dict') else {}
        result.baseline_observed_signature = extract_observed_signature(baseline_receipt_dict)

        # Run 2: Policy action applied
        # WO-ECHO-POLICY-GOLDEN-01.1a: Extract REQUESTED signature before run
        result.policy_requested_signature = extract_requested_signature(action)
        result.policy_signature = result.policy_requested_signature  # Backwards compat

        t0 = time.perf_counter()

        with harness.apply_action(action):
            policy_output, policy_receipt, _ = stream_transformer_block_forward(
                X=X,
                manifest_path=manifest_path,
                block_index=block_index,
                d_head=d_head,
                verify_policy=action.verify_policy_str,
                gguf_path=gguf_path,
            )

        result.policy_duration_ms = (time.perf_counter() - t0) * 1000
        result.policy_hash = sha256_array(policy_output)
        result.output_shape = list(policy_output.shape)

        # WO-ECHO-POLICY-GOLDEN-01.1a: Extract OBSERVED signature from receipt
        policy_receipt_dict = policy_receipt.to_dict() if hasattr(policy_receipt, 'to_dict') else {}
        result.policy_observed_signature = extract_observed_signature(policy_receipt_dict)

        # Compare outputs
        result.cosine = cosine_similarity(baseline_output, policy_output)
        result.max_abs_error = float(np.abs(baseline_output - policy_output).max())
        result.passed = result.cosine >= threshold

        # WO-ECHO-POLICY-GOLDEN-01.1: Bitwise identity
        result.bitwise_identical = (result.baseline_hash == result.policy_hash)

        # WO-ECHO-POLICY-GOLDEN-01.1a: Signature comparison using OBSERVED signatures
        result.signatures_differ = (result.baseline_observed_signature != result.policy_observed_signature)

        # WO-ECHO-POLICY-GOLDEN-01.1a: Detect requested vs observed mismatches (placebo detection)
        # Uses full signature comparison via __eq__, not just matmul_impl
        if result.baseline_requested_signature and result.baseline_observed_signature:
            result.baseline_req_vs_obs_mismatch = (
                result.baseline_requested_signature != result.baseline_observed_signature
            )
            result.baseline_mismatch_fields = result.baseline_requested_signature.mismatch_fields(
                result.baseline_observed_signature
            )
        if result.policy_requested_signature and result.policy_observed_signature:
            result.policy_req_vs_obs_mismatch = (
                result.policy_requested_signature != result.policy_observed_signature
            )
            result.policy_mismatch_fields = result.policy_requested_signature.mismatch_fields(
                result.policy_observed_signature
            )

    except Exception as e:
        result.error = str(e)
        result.passed = False

    return result


# =============================================================================
# Batch Verification
# =============================================================================

@dataclass
class GoldenSweepResult:
    """
    Result of sweeping all action combinations.

    WO-ECHO-POLICY-GOLDEN-01.1: Added bitwise_identical_count, signatures_differed_count.
    WO-ECHO-POLICY-GOLDEN-01.1a: Two-tier hash system (content_sha256 + file_sha256).
    """
    schema: str = "echo.policy.golden.v1.1"
    work_order: str = "WO-ECHO-POLICY-GOLDEN-01.1a"
    timestamp: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"))

    manifest_path: str = ""
    gguf_path: str = ""

    action_space_size: int = 24
    n_trials_per_action: int = 1
    total_tests: int = 0

    # Aggregate results
    passed: int = 0
    failed: int = 0
    min_cosine: float = 1.0
    max_cosine: float = 0.0
    mean_cosine: float = 0.0

    # WO-ECHO-POLICY-GOLDEN-01.1: New aggregate counters
    bitwise_identical_count: int = 0  # How many tests had exact SHA256 match
    signatures_differed_count: int = 0  # How many tests had different codepaths

    # Per-action summary
    per_action_summary: List[Dict[str, Any]] = field(default_factory=list)

    # Failed tests
    failed_tests: List[Dict[str, Any]] = field(default_factory=list)

    # Timing
    total_duration_ms: float = 0.0

    # WO-ECHO-POLICY-GOLDEN-01.1a: Two-tier hash system
    content_sha256: str = ""  # Semantic fingerprint (excludes hash fields)
    file_sha256: str = ""  # Literal bytes on disk (what sha256sum shows)

    # Status
    status: str = "PENDING"

    def to_dict(self) -> Dict[str, Any]:
        return {
            "schema": self.schema,
            "work_order": self.work_order,
            "timestamp": self.timestamp,
            "content_sha256": self.content_sha256,
            "file_sha256": self.file_sha256,
            "manifest_path": self.manifest_path,
            "gguf_path": self.gguf_path,
            "action_space_size": self.action_space_size,
            "n_trials_per_action": self.n_trials_per_action,
            "total_tests": self.total_tests,
            "results": {
                "passed": self.passed,
                "failed": self.failed,
                "min_cosine": self.min_cosine,
                "max_cosine": self.max_cosine,
                "mean_cosine": self.mean_cosine,
                "bitwise_identical_count": self.bitwise_identical_count,
                "signatures_differed_count": self.signatures_differed_count,
            },
            "per_action_summary": self.per_action_summary,
            "failed_tests": self.failed_tests,
            "total_duration_ms": self.total_duration_ms,
            "status": self.status,
        }


def sweep_all_actions(
    X_generator,
    manifest_path: Union[str, Path],
    block_index: int,
    gguf_path: Optional[Union[str, Path]] = None,
    n_trials: int = 1,
    threshold: float = 0.9999,
    verbose: bool = False,
) -> GoldenSweepResult:
    """
    Sweep all 24 action combinations and verify each.

    Args:
        X_generator: Callable that returns input tensor for each trial
        manifest_path: Path to CDNA manifest
        block_index: Transformer block index
        gguf_path: Path to GGUF file for norm weights
        n_trials: Number of trials per action
        threshold: Minimum cosine similarity for PASS
        verbose: Print progress

    Returns:
        GoldenSweepResult with aggregate results
    """
    from helix_cdc.runtime.policy_harness import TOTAL_ACTION_COMBINATIONS

    all_actions = PolicyAction.all_actions()
    harness = PolicyHarness.default()

    result = GoldenSweepResult(
        manifest_path=str(manifest_path),
        gguf_path=str(gguf_path) if gguf_path else "",
        action_space_size=TOTAL_ACTION_COMBINATIONS,
        n_trials_per_action=n_trials,
        total_tests=TOTAL_ACTION_COMBINATIONS * n_trials,
    )

    all_cosines = []
    t0_total = time.perf_counter()

    for action_idx, action in enumerate(all_actions):
        action_cosines = []
        action_passed = 0
        action_durations = []

        if verbose:
            action_dict = action.to_dict()
            print(f"Action {action_idx}/{TOTAL_ACTION_COMBINATIONS}: "
                  f"verify={action_dict['verify_policy']}, "
                  f"cpp={action_dict['cpp_kernel']}, "
                  f"fused={action_dict['fused_matmul']}, "
                  f"fibpi={action_dict['fibpi_mode']}")

        action_bitwise_identical = 0
        action_signatures_differed = 0
        first_baseline_sig = None
        first_policy_sig = None

        for trial in range(n_trials):
            X = X_generator()

            verification = verify_policy_correctness(
                X=X,
                manifest_path=manifest_path,
                block_index=block_index,
                action=action,
                gguf_path=gguf_path,
                threshold=threshold,
                harness=harness,
            )

            action_cosines.append(verification.cosine)
            action_durations.append(verification.policy_duration_ms)
            all_cosines.append(verification.cosine)

            # WO-ECHO-POLICY-GOLDEN-01.1: Track new counters
            if verification.bitwise_identical:
                action_bitwise_identical += 1
                result.bitwise_identical_count += 1
            if verification.signatures_differ:
                action_signatures_differed += 1
                result.signatures_differed_count += 1

            # Capture first signatures for summary
            if trial == 0:
                first_baseline_sig = verification.baseline_signature
                first_policy_sig = verification.policy_signature

            if verification.passed:
                action_passed += 1
                result.passed += 1
            else:
                result.failed += 1
                result.failed_tests.append({
                    "action_index": action_idx,
                    "trial": trial,
                    "cosine": verification.cosine,
                    "error": verification.error,
                })

            if verbose:
                status = "PASS" if verification.passed else "FAIL"
                bitwise = "BITWISE" if verification.bitwise_identical else "cosine"
                sig_diff = "SIG_DIFF" if verification.signatures_differ else "same_sig"
                print(f"  Trial {trial+1}/{n_trials}: cosine={verification.cosine:.6f} [{status}] [{bitwise}] [{sig_diff}]")

        # Per-action summary with WO-ECHO-POLICY-GOLDEN-01.1 additions
        result.per_action_summary.append({
            "action_index": action_idx,
            "action": action.to_dict(),
            "trials": n_trials,
            "passed": action_passed,
            "min_cosine": min(action_cosines) if action_cosines else 0.0,
            "max_cosine": max(action_cosines) if action_cosines else 0.0,
            "mean_cosine": float(np.mean(action_cosines)) if action_cosines else 0.0,
            "mean_duration_ms": float(np.mean(action_durations)) if action_durations else 0.0,
            # WO-ECHO-POLICY-GOLDEN-01.1: Signature info
            "baseline_signature": first_baseline_sig.to_dict() if first_baseline_sig else None,
            "policy_signature": first_policy_sig.to_dict() if first_policy_sig else None,
            "signatures_differ": action_signatures_differed > 0,
            "bitwise_identical": action_bitwise_identical == n_trials,
        })

    result.total_duration_ms = (time.perf_counter() - t0_total) * 1000

    if all_cosines:
        result.min_cosine = min(all_cosines)
        result.max_cosine = max(all_cosines)
        result.mean_cosine = float(np.mean(all_cosines))

    result.status = "PASS" if result.failed == 0 else "FAIL"

    return result


# =============================================================================
# Self-test
# =============================================================================

if __name__ == "__main__":
    print("=" * 60)
    print("WO-ECHO-POLICY-GOLDEN-01 - Golden Verifier Self-Test")
    print("=" * 60)
    print()

    # Test helper functions
    print("1. Helper functions")
    arr1 = np.array([1.0, 2.0, 3.0])
    arr2 = np.array([1.0, 2.0, 3.0])
    arr3 = np.array([3.0, 2.0, 1.0])

    print(f"   sha256_array: {sha256_array(arr1)}")
    print(f"   cosine(arr1, arr1): {cosine_similarity(arr1, arr1):.6f}")
    print(f"   cosine(arr1, arr2): {cosine_similarity(arr1, arr2):.6f}")
    print(f"   cosine(arr1, arr3): {cosine_similarity(arr1, arr3):.6f}")

    # Test GoldenVerificationResult
    print("\n2. GoldenVerificationResult")
    result = GoldenVerificationResult(
        baseline_hash="abc123",
        policy_hash="def456",
        cosine=0.999912,
        passed=True,
        action_used={"verify_policy": "always"},
    )
    d = result.to_dict()
    print(f"   to_dict keys: {list(d.keys())}")
    print(f"   passed: {d['passed']}")

    # Test PolicyAction enumeration
    print("\n3. PolicyAction enumeration")
    all_actions = PolicyAction.all_actions()
    print(f"   Total actions: {len(all_actions)}")
    print(f"   Action 0: {all_actions[0].to_dict()}")
    print(f"   Action 23: {all_actions[23].to_dict()}")

    print()
    print("=" * 60)
    print("Self-test PASSED (mock mode - no real block forward)")
    print("=" * 60)
    print()
    print("To run real verification:")
    print("  PYTHONPATH=. python3 tools/policy_golden_sweep.py \\")
    print("      --manifest seeds/hybrid_manifest_v2_full_cdna2.json \\")
    print("      --gguf tmp/rebuilt_from_hybrid_cdna_v2.gguf \\")
    print("      --n-trials 3")
