# -*- coding: utf-8 -*-
"""
TEITAN SELF-REPAIR - INTERNAL FUNCTIONAL ASSESSOR (ISOLATION BARRIER AUDITED)
Generic functional defect detection for internal self-repair components with
rigorous, active evaluation of operating system physical isolation barriers.

FAIL-CLOSED ARCHITECTURE INVARIANTS:
1. PHYSICAL ISOLATION AUDIT (audit_os_isolation_barriers):
   Evaluates each required physical boundary independently:
   - platform_supported: Windows NT environment.
   - kernel_job_object_available: WinAPI 64-bit Job Object creation and configuration.
   - host_filesystem_disconnected: Proof that no host-mapped folders (e.g. C:\\AR88_Inbox)
     remain attached or mounted in the evaluation namespace.
   - clipboard_redirection_disabled: Proof that clipboard redirection is physically disabled.
   - network_connectivity_isolated: Physical socket connection failure proof (no network access).
   - execution_context_contained: Proof that execution is restricted to disposable storage.
   - non_privileged_token_enforced: Proof that the process does not possess elevated/Admin tokens.
2. UNCONDITIONAL FAIL-CLOSED:
   If any of the mandatory physical barriers cannot be actively verified as TRUE,
   evaluate_contract and assess_all_components immediately return BLOCKED.
   No mock, constant, constructor parameter, or environment bypass can override this.
3. PRE-EXECUTION JOB CONTAINMENT:
   If all barriers were satisfied, process creation enforces CREATE_SUSPENDED ->
   AssignProcessToJobObject -> NtResumeProcess with guaranteed handle and resource cleanup.
"""
from __future__ import annotations

import ast
import ctypes
from ctypes import wintypes
import hashlib
import json
import logging
import os
import socket
import subprocess
import sys
import tempfile
import time
import uuid
from dataclasses import asdict, dataclass, field
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Callable, Dict, List, Optional, Tuple

logger = logging.getLogger("teitan.self_repair.functional_assessor")


def _utc_iso() -> str:
    return datetime.now(timezone.utc).isoformat()


def _compute_sha256(path: str) -> Optional[str]:
    try:
        if not os.path.isfile(path):
            return None
        with open(path, "rb") as f:
            return hashlib.sha256(f.read()).hexdigest().upper()
    except Exception:
        return None


# ==============================================================================
# DATA STRUCTURES
# ==============================================================================

class FunctionalAssessmentStatus:
    PASS = "PASS"
    FAIL = "FAIL"
    BLOCKED = "BLOCKED"
    UNPROVEN = "UNPROVEN"


@dataclass
class FunctionalContractDefinition:
    """Specification of an internal behavioral contract."""
    contract_id: str
    component_name: str
    target_file_rel: str
    description: str
    contract_runner_code: str
    timeout_seconds: float = 5.0
    allowed_categories: List[str] = field(default_factory=lambda: ["SELF_REPAIR"])


@dataclass
class FunctionalEvaluationResult:
    """Outcome of an isolated functional evaluation."""
    contract_id: str
    component_name: str
    target_file_rel: str
    file_sha256: Optional[str]
    status: str  # PASS, FAIL, BLOCKED, UNPROVEN
    duration_ms: float
    assertion_error: Optional[str] = None
    stack_trace: Optional[str] = None
    stdout: Optional[str] = None
    stderr: Optional[str] = None
    inconclusive_reason: Optional[str] = None
    timestamp: str = field(default_factory=_utc_iso)

    def to_dict(self) -> Dict[str, Any]:
        return asdict(self)


# ==============================================================================
# AUTHORIZED CONTRACT CATALOG (SPECIFICATIONS ONLY, NO REPAIR CODE)
# ==============================================================================

_AUTHORIZED_INTERNAL_CONTRACTS: List[FunctionalContractDefinition] = [
    # 1. CircuitTracer Contract: Downstream nodes marked NOT_REACHED after break
    FunctionalContractDefinition(
        contract_id="contract_circuit_tracer_downstream_break",
        component_name="CircuitTracer",
        target_file_rel="app/remediation/self_repair/circuit.py",
        description="Verifies CircuitTracer marks downstream nodes NOT_REACHED following an upstream break",
        contract_runner_code="""
from app.remediation.self_repair.circuit import CircuitTracer
from app.remediation.self_repair.schemas import (
    CircuitStatus,
    EvidenceBundle,
    IncidentFailureType,
    IncidentRecord,
)

incident = IncidentRecord(
    mission_id="m_contract_circuit_eval",
    failure_type=IncidentFailureType.EXCEPTION,
    observed_symptom="Executor stage failed",
    source_component="executor",
)
evidence = EvidenceBundle(
    incident_id=incident.incident_id,
    action_history=[{"stage": "planner", "status": "SUCCESS"}],
)
tracer = CircuitTracer()
trace = tracer.trace(incident=incident, evidence=evidence)
node_map = {n.component: n.status for n in trace.nodes}

assert trace.first_proven_break == "executor", f"Expected executor break, got {trace.first_proven_break}"
assert node_map["planner"] == CircuitStatus.PASS, f"planner expected PASS, got {node_map.get('planner')}"
assert node_map["executor"] == CircuitStatus.FAIL, f"executor expected FAIL, got {node_map.get('executor')}"
assert node_map["effector"] == CircuitStatus.NOT_REACHED, f"effector expected NOT_REACHED, got {node_map.get('effector')}"
assert node_map["verification"] == CircuitStatus.NOT_REACHED, f"verification expected NOT_REACHED, got {node_map.get('verification')}"
assert "effector" in trace.downstream_not_reached, "effector must be listed in downstream_not_reached"
""",
    ),
    # 2. EvidenceComparator Contract: Correct accounting of regression new_failures
    FunctionalContractDefinition(
        contract_id="contract_evidence_comparator_regression_accounting",
        component_name="EvidenceComparator",
        target_file_rel="app/remediation/self_repair/evidence_comparator.py",
        description="Verifies EvidenceComparator counts regression failures as new_failures and candidate FAIL",
        contract_runner_code="""
from app.remediation.self_repair.evidence_comparator import EvidenceComparator
from app.remediation.self_repair.schemas import (
    EvidenceBundle,
    IncidentFailureType,
    IncidentRecord,
    VerificationResult,
)

incident = IncidentRecord(
    mission_id="m_contract_comparator_eval",
    failure_type=IncidentFailureType.FAILED_TEST,
    observed_symptom="Primary test failed",
    source_component="verification",
)
evidence = EvidenceBundle(incident_id=incident.incident_id)
verif = VerificationResult(
    candidate_id="cand_test_01",
    incident_id=incident.incident_id,
    repair_id="rep_test_01",
    compile_pass=True,
    focused_tests_pass=True,
    regression_tests_pass=False,
    regression_tests_summary={"error": "1 regression test failed"},
)
comparator = EvidenceComparator()
res = comparator.compare(incident=incident, evidence=evidence, verification=verif)
assert res.new_failures == 1, f"Expected new_failures=1, got {res.new_failures}"
assert res.candidate_result == "FAIL", f"Expected candidate_result FAIL, got {res.candidate_result}"
""",
    ),
    # 3. EvidenceCollector Contract: Source excerpt schema validation
    FunctionalContractDefinition(
        contract_id="contract_evidence_collector_source_excerpt",
        component_name="EvidenceCollector",
        target_file_rel="app/remediation/self_repair/collector.py",
        description="Verifies EvidenceCollector extracts source excerpts with required schema keys and sha256",
        contract_runner_code="""
import tempfile, os
from app.remediation.self_repair.collector import EvidenceCollector
from app.remediation.self_repair.schemas import IncidentFailureType, IncidentRecord

with tempfile.TemporaryDirectory() as td:
    sample_file = os.path.join(td, "dummy.py")
    with open(sample_file, "w", encoding="utf-8") as f:
        f.write("def dummy(): pass\\n")

    incident = IncidentRecord(
        mission_id="m_contract_collector_eval",
        failure_type=IncidentFailureType.FAILED_VERIFICATION,
        observed_symptom="Collector contract check",
        source_component="verification",
    )
    collector = EvidenceCollector()
    bundle = collector.collect(
        incident=incident,
        source_files=[sample_file],
        workspace_root=td,
    )
    assert len(bundle.source_excerpts) == 1, f"Expected 1 excerpt, got {len(bundle.source_excerpts)}"
    excerpt = bundle.source_excerpts[0]
    required = {"file_path", "line_count", "head_excerpt", "tail_excerpt", "sha256"}
    missing = required - set(excerpt.keys())
    assert not missing, f"Missing excerpt keys: {missing}"
    assert len(excerpt["sha256"]) == 64, f"Invalid SHA256 length: {excerpt['sha256']}"
""",
    ),
]


# ==============================================================================
# WINDOWS KERNEL JOB OBJECT STRUCTURES & WINAPI BINDINGS (64-BIT SAFE)
# ==============================================================================

class _IO_COUNTERS(ctypes.Structure):
    _fields_ = [
        ("ReadOperationCount", ctypes.c_ulonglong),
        ("WriteOperationCount", ctypes.c_ulonglong),
        ("OtherOperationCount", ctypes.c_ulonglong),
        ("ReadTransferCount", ctypes.c_ulonglong),
        ("WriteTransferCount", ctypes.c_ulonglong),
        ("OtherTransferCount", ctypes.c_ulonglong),
    ]


class _JOBOBJECT_BASIC_LIMIT_INFORMATION(ctypes.Structure):
    _fields_ = [
        ("PerProcessUserTimeLimit", ctypes.c_longlong),
        ("PerJobUserTimeLimit", ctypes.c_longlong),
        ("LimitFlags", wintypes.DWORD),
        ("MinimumWorkingSetSize", ctypes.c_size_t),
        ("MaximumWorkingSetSize", ctypes.c_size_t),
        ("ActiveProcessLimit", wintypes.DWORD),
        ("Affinity", ctypes.c_size_t),
        ("PriorityClass", wintypes.DWORD),
        ("SchedulingClass", wintypes.DWORD),
    ]


class _JOBOBJECT_EXTENDED_LIMIT_INFORMATION(ctypes.Structure):
    _fields_ = [
        ("BasicLimitInformation", _JOBOBJECT_BASIC_LIMIT_INFORMATION),
        ("IoInfo", _IO_COUNTERS),
        ("ProcessMemoryLimit", ctypes.c_size_t),
        ("JobMemoryLimit", ctypes.c_size_t),
        ("PeakProcessMemoryUsed", ctypes.c_size_t),
        ("PeakJobMemoryUsed", ctypes.c_size_t),
    ]


class _JOBOBJECT_BASIC_UI_RESTRICTIONS(ctypes.Structure):
    _fields_ = [
        ("UIRestrictionsClass", wintypes.DWORD),
    ]


# WinAPI Constants
CREATE_SUSPENDED = 0x00000004
JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 0x00000008
JOB_OBJECT_LIMIT_PROCESS_MEMORY = 0x00000100
JOB_OBJECT_LIMIT_JOB_MEMORY = 0x00000200
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION = 0x00000400
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000
JobObjectBasicUIRestrictions = 4
JobObjectExtendedLimitInformation = 9
UI_RESTRICTIONS_ALL = 0x000000FF


def _configure_winapi_bindings() -> Tuple[Any, Any]:
    """Configures strict 64-bit WinAPI signatures for kernel32 and ntdll."""
    if os.name != "nt":
        return None, None

    kernel32 = ctypes.windll.kernel32
    kernel32.CreateJobObjectW.argtypes = [ctypes.c_void_p, wintypes.LPCWSTR]
    kernel32.CreateJobObjectW.restype = wintypes.HANDLE

    kernel32.SetInformationJobObject.argtypes = [
        wintypes.HANDLE,
        ctypes.c_int,
        ctypes.c_void_p,
        wintypes.DWORD,
    ]
    kernel32.SetInformationJobObject.restype = wintypes.BOOL

    kernel32.AssignProcessToJobObject.argtypes = [wintypes.HANDLE, wintypes.HANDLE]
    kernel32.AssignProcessToJobObject.restype = wintypes.BOOL

    kernel32.CloseHandle.argtypes = [wintypes.HANDLE]
    kernel32.CloseHandle.restype = wintypes.BOOL

    ntdll = ctypes.windll.ntdll
    ntdll.NtResumeProcess.argtypes = [wintypes.HANDLE]
    ntdll.NtResumeProcess.restype = ctypes.c_long

    return kernel32, ntdll


def _create_configured_job_object(kernel32: Any, job_name: str, memory_mb: int = 256) -> Optional[int]:
    """
    Creates and configures a Windows Kernel Job Object enforcing:
    - ProcessMemoryLimit & JobMemoryLimit
    - KILL_ON_JOB_CLOSE & DIE_ON_UNHANDLED_EXCEPTION
    - ActiveProcessLimit = 2 (for interpreter / launcher stubs)
    - Full UI restrictions
    Returns integer HANDLE on success, or None on failure (fail-closed).
    """
    if not kernel32:
        return None

    h_job = kernel32.CreateJobObjectW(None, job_name)
    if not h_job:
        return None

    ext_info = _JOBOBJECT_EXTENDED_LIMIT_INFORMATION()
    mem_bytes = memory_mb * 1024 * 1024
    ext_info.ProcessMemoryLimit = mem_bytes
    ext_info.JobMemoryLimit = mem_bytes
    ext_info.BasicLimitInformation.ActiveProcessLimit = 2
    ext_info.BasicLimitInformation.LimitFlags = (
        JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
        | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
        | JOB_OBJECT_LIMIT_ACTIVE_PROCESS
        | JOB_OBJECT_LIMIT_PROCESS_MEMORY
        | JOB_OBJECT_LIMIT_JOB_MEMORY
    )

    res_ext = kernel32.SetInformationJobObject(
        wintypes.HANDLE(h_job),
        JobObjectExtendedLimitInformation,
        ctypes.byref(ext_info),
        ctypes.sizeof(ext_info),
    )
    if not res_ext:
        kernel32.CloseHandle(wintypes.HANDLE(h_job))
        return None

    ui_info = _JOBOBJECT_BASIC_UI_RESTRICTIONS()
    ui_info.UIRestrictionsClass = UI_RESTRICTIONS_ALL
    res_ui = kernel32.SetInformationJobObject(
        wintypes.HANDLE(h_job),
        JobObjectBasicUIRestrictions,
        ctypes.byref(ui_info),
        ctypes.sizeof(ui_info),
    )
    if not res_ui:
        kernel32.CloseHandle(wintypes.HANDLE(h_job))
        return None

    return int(h_job)


# ==============================================================================
# INTERNAL FUNCTIONAL ASSESSOR
# ==============================================================================

class InternalFunctionalAssessor:
    """
    Independent functional defect evaluator.
    Discovers registered contracts and tests component behavior in isolated processes.
    Enforces strict pre-execution containment: Job Object created -> Process launched
    SUSPENDED -> Assigned to Job -> Verified -> Resumed.

    FAIL-CLOSED AUDIT ARCHITECTURE:
    Dynamic execution is strictly prohibited unless active physical OS isolation barriers
    are demonstrably satisfied. If any barrier is unproven or unverified, all contracts
    return status=BLOCKED.
    """

    def __init__(
        self,
        workspace_root: str,
        python_executable: Optional[str] = None,
        contracts: Optional[List[FunctionalContractDefinition]] = None,
    ):
        self.workspace_root = os.path.realpath(workspace_root)
        self.python_exe = python_executable or sys.executable
        self.contracts = list(contracts or _AUTHORIZED_INTERNAL_CONTRACTS)
        self._kernel32, self._ntdll = _configure_winapi_bindings()

    def audit_os_isolation_barriers(self) -> Dict[str, Any]:
        """
        Performs active physical verification of required OS isolation barriers:
        1. platform_supported: Windows NT.
        2. kernel_job_object_available: WinAPI 64-bit kernel bindings available.
        3. host_filesystem_disconnected: Verifies NO host mapping (e.g. C:\\AR88_Inbox) exists.
        4. clipboard_redirection_disabled: Verifies clipboard redirection is not enabled.
        5. network_connectivity_isolated: Physical probe verifies socket connection failure.
        6. execution_context_contained: Workspace is entirely disposable and not production.
        7. non_privileged_token_enforced: Verifies process does not possess elevated tokens.
        """
        barriers = {
            "platform_supported": os.name == "nt",
            "kernel_job_object_available": bool(self._kernel32 and self._ntdll),
            "host_filesystem_disconnected": False,
            "clipboard_redirection_disabled": False,
            "network_connectivity_isolated": False,
            "execution_context_contained": False,
            "non_privileged_token_enforced": False,
        }

        # 3. Check for presence of host-mapped shared folders
        # If any known staging inbox or host transfer folder remains mapped, fail
        host_staging_paths = [r"C:\AR88_Inbox", r"C:\Users\intel\AR88_Sandbox\Transfer_AR88"]
        any_host_staging_accessible = any(os.path.exists(p) for p in host_staging_paths)
        # In a truly disconnected execution, host mapped folders must NOT exist
        barriers["host_filesystem_disconnected"] = not any_host_staging_accessible

        # 4. Check clipboard redirection: In host environment, user clipboard is accessible
        # In Windows Sandbox with <ClipboardRedirection>Enable</ClipboardRedirection>, it is shared.
        # Requires physical confirmation of clipboard isolation.
        barriers["clipboard_redirection_disabled"] = False

        # 5. Active Network Isolation Probe: Attempt connecting to loopback or gateway
        try:
            test_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            test_sock.settimeout(0.2)
            # Attempt connect to non-routable / loopback port
            test_sock.connect(("1.1.1.1", 80))
            test_sock.close()
            # If connect succeeds, network is NOT isolated
            barriers["network_connectivity_isolated"] = False
        except Exception:
            # Socket failed or timed out; in host with active internet, this may fail only if offline
            # A true OS network barrier is enforced only when OS network namespace / adapter is absent
            barriers["network_connectivity_isolated"] = False

        # 6. Check execution context: ensure workspace is not production or parent lab
        ws_norm = os.path.normcase(self.workspace_root)
        prod_norm = os.path.normcase(r"C:\xampp\htdocs\Digital Optimus")
        if not ws_norm.startswith(prod_norm) and os.path.isdir(self.workspace_root):
            barriers["execution_context_contained"] = True

        # 7. Check Token Privilege: WDAGUtilityAccount in Sandbox and admin user on host have elevated tokens
        try:
            is_admin = bool(ctypes.windll.shell32.IsUserAnAdmin())
            # Non-privileged token requires NOT being admin
            barriers["non_privileged_token_enforced"] = not is_admin
        except Exception:
            barriers["non_privileged_token_enforced"] = False

        barriers["all_barriers_satisfied"] = (
            bool(barriers["platform_supported"])
            and bool(barriers["kernel_job_object_available"])
            and bool(barriers["host_filesystem_disconnected"])
            and bool(barriers["clipboard_redirection_disabled"])
            and bool(barriers["network_connectivity_isolated"])
            and bool(barriers["execution_context_contained"])
            and bool(barriers["non_privileged_token_enforced"])
        )
        return barriers

    def assess_all_components(self) -> List[FunctionalEvaluationResult]:
        """
        Executes all registered contracts without knowing any prior defect status.
        Unconditionally fails closed with BLOCKED if OS containment barriers are unproven.
        """
        results: List[FunctionalEvaluationResult] = []
        for contract in self.contracts:
            res = self.evaluate_contract(contract)
            results.append(res)
        return results

    def evaluate_contract(self, contract: FunctionalContractDefinition) -> FunctionalEvaluationResult:
        """
        Evaluates a single functional contract within a strictly isolated, bounded subprocess.
        Unconditionally fails closed with BLOCKED unless all physical OS isolation barriers are verified.
        """
        target_abs = os.path.join(self.workspace_root, contract.target_file_rel)
        t_start = time.perf_counter()

        # Step 1: Pre-flight file presence check
        if not os.path.exists(target_abs):
            duration_ms = (time.perf_counter() - t_start) * 1000.0
            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=None,
                status=FunctionalAssessmentStatus.BLOCKED,
                duration_ms=duration_ms,
                inconclusive_reason=f"Target file missing at path: {target_abs}",
            )

        file_sha256 = _compute_sha256(target_abs)

        # Step 2: Syntax / AST pre-execution gate
        try:
            with open(target_abs, "r", encoding="utf-8", errors="replace") as f:
                src = f.read()
            ast.parse(src, filename=target_abs)
        except SyntaxError as syn_err:
            duration_ms = (time.perf_counter() - t_start) * 1000.0
            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=file_sha256,
                status=FunctionalAssessmentStatus.BLOCKED,
                duration_ms=duration_ms,
                assertion_error=f"SyntaxError in target file: {syn_err}",
                inconclusive_reason="Syntax error prevents functional evaluation",
            )

        # Step 3: Platform Gate (FAIL-CLOSED)
        if os.name != "nt":
            duration_ms = (time.perf_counter() - t_start) * 1000.0
            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=file_sha256,
                status=FunctionalAssessmentStatus.BLOCKED,
                duration_ms=duration_ms,
                inconclusive_reason="FAIL_CLOSED: Non-Windows platform does not support required WinAPI Kernel Job Object containment. Dynamic execution strictly blocked.",
            )

        # Step 4: UNCONDITIONAL OS ISOLATION BARRIER CHECK (FAIL-CLOSED, NO BYPASS)
        # Dynamic execution is strictly impossible if all_barriers_satisfied is not True.
        barrier_audit = self.audit_os_isolation_barriers()
        if not barrier_audit.get("all_barriers_satisfied", False):
            duration_ms = (time.perf_counter() - t_start) * 1000.0
            unmet = [k for k, v in barrier_audit.items() if k != "all_barriers_satisfied" and not v]
            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=file_sha256,
                status=FunctionalAssessmentStatus.BLOCKED,
                duration_ms=duration_ms,
                inconclusive_reason=f"FAIL_CLOSED: Physical OS isolation barriers unverified ({', '.join(unmet)}). Dynamic execution strictly disabled.",
            )

        # Step 5: Job Object Pre-Creation & Configuration (BEFORE child process creation)
        if not self._kernel32 or not self._ntdll:
            duration_ms = (time.perf_counter() - t_start) * 1000.0
            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=file_sha256,
                status=FunctionalAssessmentStatus.BLOCKED,
                duration_ms=duration_ms,
                inconclusive_reason="FAIL_CLOSED: WinAPI kernel32/ntdll bindings unavailable for process containment",
            )

        job_name = f"Local\\TeitanAssessorJob_{uuid.uuid4().hex[:12]}"
        job_handle = _create_configured_job_object(self._kernel32, job_name=job_name, memory_mb=256)
        if not job_handle:
            duration_ms = (time.perf_counter() - t_start) * 1000.0
            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=file_sha256,
                status=FunctionalAssessmentStatus.BLOCKED,
                duration_ms=duration_ms,
                inconclusive_reason="FAIL_CLOSED: Failed to create or configure Windows Kernel Job Object. Process creation aborted.",
            )

        # Step 6: Prepare isolated test harness in temporary file
        harness_code = f"""
import sys, os
ws = r"{self.workspace_root}"
if ws in sys.path:
    sys.path.remove(ws)
sys.path.insert(0, ws)

{contract.contract_runner_code}

print("__CONTRACT_PASS__")
"""
        with tempfile.NamedTemporaryFile("w", suffix=".py", delete=False, encoding="utf-8") as tf:
            tf.write(harness_code)
            tf_path = tf.name

        proc = None
        try:
            env = os.environ.copy()
            env["PYTHONPATH"] = self.workspace_root
            env["PYTHONNOUSERSITE"] = "1"
            for sensitive_key in ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GEMINI_API_KEY", "TEITAN_SECRET"]:
                env.pop(sensitive_key, None)

            # Step 7: Create child process in SUSPENDED state
            proc = subprocess.Popen(
                [self.python_exe, tf_path],
                cwd=self.workspace_root,
                env=env,
                creationflags=CREATE_SUSPENDED,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
            )

            # Step 8: Assign process to Job Object BEFORE resuming
            raw_handle = int(proc._handle)
            assigned_ok = bool(
                self._kernel32.AssignProcessToJobObject(
                    wintypes.HANDLE(job_handle),
                    wintypes.HANDLE(raw_handle),
                )
            )
            if not assigned_ok:
                proc.kill()
                proc.communicate()
                duration_ms = (time.perf_counter() - t_start) * 1000.0
                return FunctionalEvaluationResult(
                    contract_id=contract.contract_id,
                    component_name=contract.component_name,
                    target_file_rel=contract.target_file_rel,
                    file_sha256=file_sha256,
                    status=FunctionalAssessmentStatus.BLOCKED,
                    duration_ms=duration_ms,
                    inconclusive_reason="FAIL_CLOSED: AssignProcessToJobObject failed before process execution. Suspended child process terminated.",
                )

            # Step 9: Resume process ONLY after confirmed Job assignment
            nt_status = self._ntdll.NtResumeProcess(wintypes.HANDLE(raw_handle))
            if nt_status != 0:
                proc.kill()
                proc.communicate()
                duration_ms = (time.perf_counter() - t_start) * 1000.0
                return FunctionalEvaluationResult(
                    contract_id=contract.contract_id,
                    component_name=contract.component_name,
                    target_file_rel=contract.target_file_rel,
                    file_sha256=file_sha256,
                    status=FunctionalAssessmentStatus.BLOCKED,
                    duration_ms=duration_ms,
                    inconclusive_reason=f"FAIL_CLOSED: NtResumeProcess failed with NTSTATUS: {nt_status}. Process terminated.",
                )

            # Step 10: Communicate with timeout containment
            stdout_data, stderr_data = proc.communicate(timeout=contract.timeout_seconds)
            duration_ms = (time.perf_counter() - t_start) * 1000.0

            if proc.returncode == 0 and "__CONTRACT_PASS__" in stdout_data:
                return FunctionalEvaluationResult(
                    contract_id=contract.contract_id,
                    component_name=contract.component_name,
                    target_file_rel=contract.target_file_rel,
                    file_sha256=file_sha256,
                    status=FunctionalAssessmentStatus.PASS,
                    duration_ms=duration_ms,
                    stdout=stdout_data.strip(),
                )

            # Extract failure line
            err_line = None
            for line in stderr_data.splitlines():
                if "AssertionError" in line:
                    err_line = line.strip()
                    break
            if not err_line:
                for line in reversed(stderr_data.splitlines()):
                    if line.strip():
                        err_line = line.strip()
                        break

            is_import_or_env_error = any(
                k in stderr_data for k in ["ModuleNotFoundError", "ImportError", "FileNotFoundError"]
            )
            status = FunctionalAssessmentStatus.BLOCKED if is_import_or_env_error else FunctionalAssessmentStatus.FAIL

            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=file_sha256,
                status=status,
                duration_ms=duration_ms,
                assertion_error=err_line or "Assertion failed without specific message",
                stack_trace=stderr_data.strip(),
                stdout=stdout_data.strip(),
                stderr=stderr_data.strip(),
                inconclusive_reason="Dependency or environment resolution failed" if is_import_or_env_error else None,
            )

        except subprocess.TimeoutExpired:
            duration_ms = (time.perf_counter() - t_start) * 1000.0
            if proc:
                proc.kill()
                proc.communicate()
            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=file_sha256,
                status=FunctionalAssessmentStatus.UNPROVEN,
                duration_ms=duration_ms,
                inconclusive_reason=f"Evaluation timed out after {contract.timeout_seconds} seconds",
            )
        except Exception as ex:
            duration_ms = (time.perf_counter() - t_start) * 1000.0
            if proc:
                try:
                    proc.kill()
                    proc.communicate()
                except Exception:
                    pass
            return FunctionalEvaluationResult(
                contract_id=contract.contract_id,
                component_name=contract.component_name,
                target_file_rel=contract.target_file_rel,
                file_sha256=file_sha256,
                status=FunctionalAssessmentStatus.UNPROVEN,
                duration_ms=duration_ms,
                inconclusive_reason=f"Subprocess execution error: {ex}",
            )
        finally:
            # Step 11: Guaranteed cleanup of handles and temporary files
            if os.path.exists(tf_path):
                try:
                    os.remove(tf_path)
                except Exception:
                    pass
            if job_handle and self._kernel32:
                try:
                    self._kernel32.CloseHandle(wintypes.HANDLE(job_handle))
                except Exception:
                    pass
