"""Regression tests for strict launcher/health process identity.""" from __future__ import annotations from dataclasses import replace from datetime import datetime, timedelta, timezone import json from pathlib import Path from tools.rf001_launcher_health_diagnostic import ( HandshakeExpectation, ProcessRecord, _terminate_owned_processes, atomic_write_json, evaluate_identity, strict_owned_process_ids, ) NOW = datetime(2026, 9, 29, 13, 0, tzinfo=timezone.utc) SCRIPT = r"C:\diagnostic\rf001_launcher_health_diagnostic.py" def _expectation(*, popen_pid: int = 200) -> HandshakeExpectation: return HandshakeExpectation( release_id="rf001-agent-2026.09.29.1", agent_version="2026.09.29.1", launch_nonce="fixed-unique-nonce", state="RUNNING", launcher_pid=100, popen_pid=popen_pid, launched_at=NOW.isoformat(), diagnostic_script=SCRIPT, ) def _record(pid: int, parent: int, *, seconds: float = 1.0) -> ProcessRecord: return ProcessRecord( pid=pid, parent_pid=parent, name="python.exe", executable=r"C:\Python313\python.exe", command_line=f'python "{SCRIPT}" --launch-nonce fixed-unique-nonce', created_at=(NOW + timedelta(seconds=seconds)).isoformat(), ) def _health(*, pid: int = 200) -> dict[str, object]: return { "release_id": "rf001-agent-2026.09.29.1", "agent_version": "2026.09.29.1", "launch_nonce": "fixed-unique-nonce", "state": "RUNNING", "pid": pid, "updated_at": (NOW + timedelta(seconds=2)).isoformat(), } def _evaluate( health: dict[str, object] | None, records: list[ProcessRecord], *, expectation: HandshakeExpectation | None = None, popen_alive: bool = True, health_process_alive: bool = True, ) -> dict[str, object]: return evaluate_identity( health, expectation or _expectation(), records, popen_alive=popen_alive, health_process_alive=health_process_alive, ) def test_exact_process_identity_passes() -> None: result = _evaluate(_health(), [_record(200, 100)]) assert result["identity_valid"] is True assert result["identity_model"] == "EXACT_POPEN_PROCESS" def test_wrong_nonce_fails() -> None: health = _health() health["launch_nonce"] = "wrong" assert _evaluate(health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH" def test_wrong_release_fails() -> None: health = _health() health["release_id"] = "rf001-agent-elsewhere" assert _evaluate(health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH" def test_wrong_version_fails() -> None: health = _health() health["agent_version"] = "2026.09.29.2" assert _evaluate(health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH" def test_health_before_running_state_fails() -> None: health = _health() health["state"] = "STARTING" assert _evaluate(health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH" def test_stale_health_fails() -> None: health = _health() health["updated_at"] = (NOW - timedelta(seconds=1)).isoformat() assert _evaluate(health, [_record(200, 100)])["reason"] == "STALE_HEALTH" def test_rollback_does_not_accept_previous_launch_health() -> None: previous_health = _health() previous_health["launch_nonce"] = "previous-launch-nonce" assert ( _evaluate(previous_health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH" ) def test_unrelated_pid_fails() -> None: result = _evaluate( _health(pid=300), [_record(200, 100), _record(300, 999)], ) assert result["reason"] == "UNRELATED_PID" def test_unique_expected_wrapper_child_passes_strict_lineage() -> None: result = _evaluate( _health(pid=201), [_record(200, 100), _record(201, 200)], ) assert result["identity_valid"] is True assert ( result["identity_model"] == "UNIQUE_DIRECT_CHILD_WITH_NONCE_AND_CREATION_TIME" ) assert result["pid_match"] is False def test_unexpected_grandchild_fails() -> None: result = _evaluate( _health(pid=202), [_record(200, 100), _record(201, 200), _record(202, 201)], ) assert result["reason"] == "UNEXPECTED_GRANDCHILD" def test_pid_reuse_creation_time_mismatch_fails() -> None: reused = _record(200, 100, seconds=-30) assert _evaluate(_health(), [reused])["reason"] == "PROCESS_CREATION_TIME_MISMATCH" def test_target_dies_before_health_fails() -> None: result = _evaluate(None, [_record(200, 100)], popen_alive=False) assert result["reason"] == "HEALTH_ABSENT" def test_target_writes_health_then_dies_immediately_fails() -> None: result = _evaluate( _health(), [_record(200, 100)], health_process_alive=False, ) assert result["reason"] == "HEALTH_PROCESS_DIED" def test_orphan_selection_never_includes_unrelated_process() -> None: expectation = _expectation() related = _record(201, 200) unrelated = replace(_record(300, 999), command_line="python unrelated.py") assert strict_owned_process_ids( expectation, [_record(200, 100), related, unrelated], ) == [201, 200] def test_orphan_cleanup_terminates_only_strictly_owned_processes(monkeypatch) -> None: expectation = _expectation() wrapper = _record(200, 100) child = _record(201, 200) unrelated = replace(_record(300, 999), command_line="python unrelated.py") records = [wrapper, child, unrelated] terminated: list[int] = [] monkeypatch.setattr( "tools.rf001_launcher_health_diagnostic.capture_windows_processes", lambda: records, ) monkeypatch.setattr( "tools.rf001_launcher_health_diagnostic.os.kill", lambda pid, _signal: terminated.append(pid), ) actions = _terminate_owned_processes(expectation, records) assert terminated == [201, 200] assert actions == [ {"pid": 201, "status": "TERMINATED"}, {"pid": 200, "status": "TERMINATED"}, ] def test_repeated_success_is_deterministic_with_distinct_identity() -> None: first = _expectation(popen_pid=200) second = replace( first, popen_pid=300, launch_nonce="second-unique-nonce", launched_at=(NOW + timedelta(seconds=10)).isoformat(), ) first_result = _evaluate(_health(pid=200), [_record(200, 100)], expectation=first) second_record = replace( _record(300, 100, seconds=11), command_line=f'python "{SCRIPT}" --launch-nonce second-unique-nonce', ) second_health = { **_health(pid=300), "launch_nonce": "second-unique-nonce", "updated_at": (NOW + timedelta(seconds=12)).isoformat(), } second_result = _evaluate(second_health, [second_record], expectation=second) assert first_result["identity_valid"] is True assert second_result["identity_valid"] is True assert first.launch_nonce != second.launch_nonce assert first.popen_pid != second.popen_pid def test_diagnostic_json_replacement_is_atomic(tmp_path: Path) -> None: path = tmp_path / "health.json" for sequence in range(20): atomic_write_json(path, {"sequence": sequence}) assert json.loads(path.read_text(encoding="utf-8")) == {"sequence": sequence} assert not path.with_suffix(".json.tmp").exists()