from __future__ import annotations import json import shutil import subprocess from copy import deepcopy from pathlib import Path from typing import Any import pytest ROOT = Path(__file__).resolve().parents[3] PREFLIGHT = ROOT / "scripts/reboot-recovery/agent99-live-preflight.ps1" def _function_source() -> str: source = PREFLIGHT.read_text(encoding="utf-8") start = source.index("function Get-AgentLivePreflightDecision") end = source.index("function Get-TaskReadback", start) return source[start:end] def _base_case() -> dict[str, Any]: return { "agentRootPresent": True, "manifest": { "exists": True, "sourceRevision": "a" * 40, "runtimeMatched": True, "fileCount": 14, "mismatchCount": 0, "parseError": "", }, "taskFailureCount": 0, "relayListenerCount": 1, "requiredEvidenceStaleCount": 0, "requiredEvidenceParseFailureCount": 0, "requiredEvidenceContentFailureCount": 0, "selfHealthSeverity": "ok", "selfHealthPerformanceIssueCount": 0, "staleAlertExecutionCount": 0, "alertIncomingCount": 0, "staleAlertIncomingCount": 0, "pendingCommandCount": 0, } def _with_overrides(**overrides: Any) -> dict[str, Any]: case = deepcopy(_base_case()) manifest_overrides = overrides.pop("manifest", None) case.update(overrides) if manifest_overrides: case["manifest"].update(manifest_overrides) return case def _as_list(value: Any) -> list[str]: if value is None: return [] if isinstance(value, list): return [str(item) for item in value] return [str(value)] def _run_decision(powershell: str, case: dict[str, Any]) -> dict[str, Any]: fixture = json.dumps(case, separators=(",", ":")) command = f""" {_function_source()} $case = @' {fixture} '@ | ConvertFrom-Json $parameters = @{{ AgentRootPresent = [bool]$case.agentRootPresent Manifest = $case.manifest ExpectedRuntimeFileCount = 14 TaskFailureCount = [int]$case.taskFailureCount RelayListenerCount = [int]$case.relayListenerCount RequiredEvidenceStaleCount = [int]$case.requiredEvidenceStaleCount RequiredEvidenceParseFailureCount = [int]$case.requiredEvidenceParseFailureCount RequiredEvidenceContentFailureCount = [int]$case.requiredEvidenceContentFailureCount SelfHealthSeverity = [string]$case.selfHealthSeverity SelfHealthPerformanceIssueCount = [int]$case.selfHealthPerformanceIssueCount StaleAlertExecutionCount = [int]$case.staleAlertExecutionCount AlertIncomingCount = [int]$case.alertIncomingCount StaleAlertIncomingCount = [int]$case.staleAlertIncomingCount PendingCommandCount = [int]$case.pendingCommandCount }} Get-AgentLivePreflightDecision @parameters | ConvertTo-Json -Depth 6 -Compress """ result = subprocess.run( [powershell, "-NoProfile", "-NonInteractive", "-Command", command], check=False, capture_output=True, text=True, ) assert result.returncode == 0, result.stdout + result.stderr payload = next( line for line in reversed(result.stdout.splitlines()) if line.startswith("{") ) return json.loads(payload) def test_warning_receipt_is_visible_without_weakening_integrity_blockers() -> None: source = PREFLIGHT.read_text(encoding="utf-8") decision = _function_source() assert '$warningReasons += "self_health_warning"' in decision assert '$warningReasons += "performance_warning"' in decision assert '$warningReasons += "fresh_alert_pending_next_inbox_tick"' in decision assert '"critical" { $blockingReasons += "self_health_not_ok" }' in decision assert 'default { $blockingReasons += "self_health_unclassified" }' in decision assert '$blockingReasons += "runtime_manifest_identity_invalid"' in decision assert '$blockingReasons += "runtime_manifest_mismatch"' in decision assert '$blockingReasons += "scheduled_task_unhealthy"' in decision assert '$blockingReasons += "sre_alert_relay_not_listening"' in decision assert "deploymentEligible = [bool]($blockingReasons.Count -eq 0)" in decision assert "preflightGreen = [bool]$decision.deploymentEligible" in source assert "warningReasons = $warningReasons" in source assert "selfHealthPerformanceIssues = @(" in source assert 'if ($safeHost -notmatch "^[A-Za-z0-9.:-]{1,128}$")' in source assert 'if ($reason -match "^[a-z0-9_]{1,80}$")' in source assert ( "[int]$selfCheckEvidence.safeSummary.selfHealthPerformanceIssueCount" in source ) assert 'if ($result.summary.deploymentEligible)' in source assert 'if ($selfHealthSeverity -ne "ok")' not in source def test_decision_behavior_when_powershell_is_available() -> None: powershell = shutil.which("pwsh") or shutil.which("powershell") if powershell is None: pytest.skip("PowerShell runtime is not installed on this macOS verifier") cases = ( (_base_case(), True, (), ()), ( _with_overrides( selfHealthSeverity="warning", selfHealthPerformanceIssueCount=1, ), True, (), ("self_health_warning", "performance_warning"), ), ( _with_overrides(selfHealthSeverity="critical"), False, ("self_health_not_ok",), (), ), ( _with_overrides(taskFailureCount=1), False, ("scheduled_task_unhealthy",), (), ), ( _with_overrides(manifest={"runtimeMatched": False, "mismatchCount": 1}), False, ("runtime_manifest_mismatch",), (), ), ( _with_overrides(manifest={"sourceRevision": "not-a-full-sha"}), False, ("runtime_manifest_identity_invalid",), (), ), ( _with_overrides(relayListenerCount=0), False, ("sre_alert_relay_not_listening",), (), ), ( _with_overrides(alertIncomingCount=1), True, (), ("fresh_alert_pending_next_inbox_tick",), ), ( _with_overrides( alertIncomingCount=1, staleAlertIncomingCount=1, ), False, ("pending_work_before_reboot",), (), ), ( _with_overrides(pendingCommandCount=1), False, ("pending_work_before_reboot",), (), ), ) for case, expected_eligible, expected_blockers, expected_warnings in cases: result = _run_decision(powershell, case) assert result["deploymentEligible"] is expected_eligible assert set(_as_list(result.get("blockingReasons"))) == set(expected_blockers) assert set(_as_list(result.get("warningReasons"))) == set(expected_warnings) preflight_path = str(PREFLIGHT).replace("'", "''") parser_command = ( "$tokens=$null; $errors=$null; " "[System.Management.Automation.Language.Parser]::ParseFile(" f"'{preflight_path}', [ref]$tokens, [ref]$errors) | Out-Null; " "if ($errors.Count -gt 0) { " "$errors | ForEach-Object { $_.Message }; exit 1 }" ) parsed = subprocess.run( [ powershell, "-NoProfile", "-NonInteractive", "-Command", parser_command, ], check=False, capture_output=True, text=True, ) assert parsed.returncode == 0, parsed.stdout + parsed.stderr