teleo-infrastructure/scripts/run_leo_identity_reconstruction_canary.py

439 lines
19 KiB
Python

#!/usr/bin/env python3
"""Prove manifest-driven Leo identity reconstruction across a cold restart."""
from __future__ import annotations
import argparse
import json
import os
import shutil
import signal
import subprocess
import sys
import tempfile
import time
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
if __package__ in {None, ""}:
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from scripts import leo_behavior_manifest as behavior
from scripts import leo_identity_manifest as identity
from scripts import leo_identity_profile as profile_runtime
SCHEMA = "livingip.leoIdentityReconstructionReceipt.v1"
class CanaryError(RuntimeError):
"""The disposable identity runtime did not satisfy its T2 contract."""
def _require(condition: bool, message: str) -> None:
if not condition:
raise CanaryError(message)
def _process_group_absent(process_group: int) -> bool:
try:
os.killpg(process_group, 0)
except ProcessLookupError:
return True
except PermissionError:
return False
return False
def _wait_for_process_group_absence(process_group: int, timeout_seconds: float = 5) -> bool:
deadline = time.monotonic() + timeout_seconds
while time.monotonic() < deadline:
if _process_group_absent(process_group):
return True
time.sleep(0.02)
return _process_group_absent(process_group)
def _signal_process_group(process_group: int, signal_number: signal.Signals) -> bool:
try:
os.killpg(process_group, signal_number)
return True
except (ProcessLookupError, PermissionError):
return False
def _cleanup_remaining_process_group(process_group: int) -> str | None:
if not _signal_process_group(process_group, signal.SIGTERM):
return None
if _wait_for_process_group_absence(process_group, timeout_seconds=1):
return "SIGTERM"
if not _signal_process_group(process_group, signal.SIGKILL):
return "SIGTERM"
return "SIGKILL"
def _run_query_child(
*,
deployment_root: Path,
profile: Path,
source_root: Path,
hermes_root: Path,
timeout_seconds: float = 60,
) -> dict[str, Any]:
command = [
sys.executable,
"-m",
"scripts.leo_identity_profile",
"query",
"--profile",
str(profile),
"--source-root",
str(source_root),
"--hermes-root",
str(hermes_root),
"--deployment-root",
str(deployment_root),
"--query",
profile_runtime.FIXED_QUERY,
]
process = subprocess.Popen(
command,
cwd=deployment_root,
env={**os.environ, "PYTHONDONTWRITEBYTECODE": "1"},
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True,
)
timed_out = False
terminated_with: str | None = None
stdout = ""
stderr = ""
process_group_absent_after_wait = False
orphan_cleanup_required = False
try:
try:
stdout, stderr = process.communicate(timeout=timeout_seconds)
except subprocess.TimeoutExpired:
timed_out = True
if _signal_process_group(process.pid, signal.SIGTERM):
terminated_with = "SIGTERM"
try:
stdout, stderr = process.communicate(timeout=5)
except subprocess.TimeoutExpired:
if _signal_process_group(process.pid, signal.SIGKILL):
terminated_with = "SIGKILL"
stdout, stderr = process.communicate(timeout=5)
finally:
if process.poll() is None:
if _signal_process_group(process.pid, signal.SIGTERM):
terminated_with = terminated_with or "SIGTERM"
try:
process.communicate(timeout=5)
except subprocess.TimeoutExpired:
if _signal_process_group(process.pid, signal.SIGKILL):
terminated_with = "SIGKILL"
process.communicate(timeout=5)
orphan_cleanup_required = not _process_group_absent(process.pid)
if orphan_cleanup_required:
terminated_with = _cleanup_remaining_process_group(process.pid) or terminated_with
process_group_absent_after_wait = _wait_for_process_group_absence(process.pid)
try:
payload = json.loads(stdout.strip().splitlines()[-1]) if stdout.strip() else {}
except json.JSONDecodeError as exc:
raise CanaryError("identity child returned invalid JSON") from exc
return {
"command": command,
"launcher_pid": process.pid,
"returncode": process.returncode,
"timed_out": timed_out,
"terminated_with": terminated_with,
"orphan_cleanup_required": orphan_cleanup_required,
"stdout": payload,
"stderr_sha256": behavior.sha256_bytes(stderr.encode("utf-8")),
"process_group_absent_after_wait": process_group_absent_after_wait,
}
def _query_passed(child: dict[str, Any]) -> bool:
payload = child.get("stdout") or {}
return bool(
child.get("returncode") == 0
and child.get("timed_out") is False
and child.get("orphan_cleanup_required") is False
and child.get("process_group_absent_after_wait") is True
and payload.get("schema") == profile_runtime.QUERY_RECEIPT_SCHEMA
and payload.get("status") == "pass"
)
def _drift_attempt(
*,
deployment_root: Path,
source_root: Path,
hermes_root: Path,
drift_profile: Path,
) -> dict[str, Any]:
with (drift_profile / "SOUL.md").open("a", encoding="utf-8") as handle:
handle.write("\nInjected drift must fail closed.\n")
child = _run_query_child(
deployment_root=deployment_root,
profile=drift_profile,
source_root=source_root,
hermes_root=hermes_root,
)
child["fail_closed"] = bool(
child["returncode"] == 3
and child["timed_out"] is False
and child["orphan_cleanup_required"] is False
and child["process_group_absent_after_wait"] is True
and (child.get("stdout") or {}).get("error") == "identity_drift"
and "compiled view drift detected" in str((child.get("stdout") or {}).get("message"))
)
child["answer_returned"] = bool((child.get("stdout") or {}).get("answer"))
return child
def run_canary(args: argparse.Namespace) -> tuple[dict[str, Any], int]:
output = args.output.resolve()
temporary_root = Path(tempfile.mkdtemp(prefix="leo-identity-reconstruction-"))
report: dict[str, Any] = {
"schema": SCHEMA,
"generated_at_utc": datetime.now(UTC).isoformat(),
"required_tier": "T2_runtime",
"mode": "drift_before_restart"
if args.inject_drift_before_restart
else "successful_restart_plus_drift_negative",
"fixed_query": profile_runtime.FIXED_QUERY,
"fixed_query_sha256": behavior.sha256_bytes(profile_runtime.FIXED_QUERY.encode("utf-8")),
"production_profile_replaced": False,
"production_database_contacted": False,
"telegram_message_sent": False,
"actual_hosted_model_call_performed": False,
"errors": [],
}
exit_code = 1
try:
behavior_manifest = behavior.build_manifest(args.profile_template, args.hermes_root, args.deployment_root)
identity.validate_behavior_manifest(behavior_manifest)
manifest = identity.build_identity_manifest(
behavior_manifest=behavior_manifest,
database_fingerprint_path=args.database_fingerprint,
constitution_path=args.constitution,
database_identity_path=args.database_identity,
source_root=args.source_root,
)
report["manifest"] = manifest
report["behavior_observation_before_compile"] = {
"behavior_sha256": behavior_manifest["behavior_sha256"],
"identity_runtime_sha256": behavior_manifest["identity_runtime_sha256"],
"source_commit": behavior_manifest["teleo_infrastructure_runtime"]["git_head"],
}
compiled_profile = temporary_root / "first-profile"
report["compile"] = profile_runtime.compile_profile(
manifest,
source_root=args.source_root,
profile_template=args.profile_template,
profile=compiled_profile,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
compiled_behavior_before_query = behavior.build_manifest(
compiled_profile, args.hermes_root, args.deployment_root
)
report["compiled_profile_before_query"] = {
"behavior_sha256": compiled_behavior_before_query["behavior_sha256"],
"identity_runtime_sha256": compiled_behavior_before_query["identity_runtime_sha256"],
}
first = _run_query_child(
deployment_root=args.deployment_root,
profile=compiled_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
)
report["first_start"] = first
_require(_query_passed(first), "first disposable identity process did not answer successfully")
after_first = behavior.build_manifest(compiled_profile, args.hermes_root, args.deployment_root)
report["session_boundary_readback"] = {
"full_behavior_changed_after_session": after_first["behavior_sha256"]
!= compiled_behavior_before_query["behavior_sha256"],
"identity_runtime_unchanged_after_session": after_first["identity_runtime_sha256"]
== compiled_behavior_before_query["identity_runtime_sha256"],
"session_file_count": len(list((compiled_profile / "sessions").glob("*.json"))),
"session_classification": "temporary_noncanonical",
"session_used_as_output_provenance": False,
}
if args.inject_drift_before_restart:
with (compiled_profile / "SOUL.md").open("a", encoding="utf-8") as handle:
handle.write("\nInjected pre-restart drift.\n")
rejected = _run_query_child(
deployment_root=args.deployment_root,
profile=compiled_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
)
report["pre_restart_drift"] = rejected
report["drift_target"] = "compiled SOUL.md generated view"
report["second_start_attempted"] = False
report["gates"] = {
"first_start_passed": True,
"first_process_stopped": first["process_group_absent_after_wait"],
"drift_detected_before_restart": rejected["returncode"] == 3
and (rejected.get("stdout") or {}).get("error") == "identity_drift",
"drift_returned_no_answer": not bool((rejected.get("stdout") or {}).get("answer")),
"drift_process_stopped": rejected["process_group_absent_after_wait"],
"drift_process_had_no_orphan_cleanup": rejected["orphan_cleanup_required"] is False,
"second_start_not_attempted": True,
}
report["status"] = "pass" if all(report["gates"].values()) else "fail"
else:
profile_runtime.verify_profile(
compiled_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
report["pre_restart_verification"] = "pass"
report["second_start_attempted"] = True
restarted_profile = temporary_root / "restart-profile"
report["restart_compile"] = profile_runtime.compile_profile(
manifest,
source_root=args.source_root,
profile_template=args.profile_template,
profile=restarted_profile,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
profile_runtime.verify_profile(
restarted_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
second = _run_query_child(
deployment_root=args.deployment_root,
profile=restarted_profile,
source_root=args.source_root,
hermes_root=args.hermes_root,
)
report["restart"] = second
_require(_query_passed(second), "restarted disposable identity process did not answer successfully")
first_payload = first["stdout"]
second_payload = second["stdout"]
drift_profile = temporary_root / "drift-profile"
report["drift_compile"] = profile_runtime.compile_profile(
manifest,
source_root=args.source_root,
profile_template=args.profile_template,
profile=drift_profile,
hermes_root=args.hermes_root,
deployment_root=args.deployment_root,
)
drift = _drift_attempt(
deployment_root=args.deployment_root,
source_root=args.source_root,
hermes_root=args.hermes_root,
drift_profile=drift_profile,
)
report["drift_negative"] = drift
report["drift_target"] = "compiled SOUL.md generated view"
report["gates"] = {
"manifest_generated": identity._is_sha256(manifest["manifest_sha256"]),
"views_compiled_and_bound": report["compile"]["status"] == "pass",
"first_start_passed": True,
"first_process_stopped": first["process_group_absent_after_wait"],
"pre_restart_verification_passed": True,
"restart_profile_recompiled_from_manifest": report["restart_compile"]["status"] == "pass",
"restart_profile_started_without_sessions": report["restart_compile"][
"session_directories_started_empty"
],
"restart_passed": True,
"restart_process_is_distinct": first_payload["process_id"] != second_payload["process_id"]
and first_payload["runtime_instance_id"] != second_payload["runtime_instance_id"],
"identity_inputs_reproduced": first_payload["identity_inputs_sha256"]
== second_payload["identity_inputs_sha256"],
"manifest_reproduced": first_payload["manifest_sha256"] == second_payload["manifest_sha256"],
"query_reproduced": first_payload["query_sha256"] == second_payload["query_sha256"],
"answer_and_provenance_explainable": first_payload["answer_sha256"] == second_payload["answer_sha256"]
and first_payload["output_provenance"] == second_payload["output_provenance"],
"session_excluded_from_identity": report["session_boundary_readback"][
"identity_runtime_unchanged_after_session"
],
"drift_failed_closed": drift["fail_closed"] and not drift["answer_returned"],
"drift_profile_started_without_sessions": report["drift_compile"]["session_directories_started_empty"],
"drift_process_stopped": drift["process_group_absent_after_wait"],
"drift_process_had_no_orphan_cleanup": drift["orphan_cleanup_required"] is False,
"restart_process_stopped": second["process_group_absent_after_wait"],
}
report["status"] = "pass" if all(report["gates"].values()) else "fail"
if report["status"] == "pass":
exit_code = 0
except (CanaryError, identity.IdentityManifestError, OSError, subprocess.SubprocessError) as exc:
report["status"] = "fail"
report["errors"].append({"type": type(exc).__name__, "message": str(exc)})
finally:
shutil.rmtree(temporary_root, ignore_errors=True)
report["cleanup"] = {
"temporary_root_removed": not temporary_root.exists(),
"no_profile_retained": not temporary_root.exists(),
}
if not all(report["cleanup"].values()):
report["status"] = "fail"
exit_code = 1
positive_restart_passed = report.get("status") == "pass" and not args.inject_drift_before_restart
report["current_tier"] = "T2_runtime" if positive_restart_passed else "T1_model"
report["goal_tier_satisfied"] = positive_restart_passed
report["runtime_component_proven"] = (
"fresh_profile_recompile_plus_distinct_process_restart"
if positive_restart_passed
else "first_local_process_plus_pre_restart_drift_refusal"
)
report["runtime_variant"] = "local_deterministic_identity_compiler_readback"
report["tier_basis"] = (
"Capability Tier Proof defines T2_runtime as local API/runtime behavior with restart where relevant; "
"this is compiler-process runtime proof and explicitly excludes GatewayRunner and hosted-model proof."
if positive_restart_passed
else "This negative component does not complete the required restart path, so it remains below T2_runtime."
)
report["claim_ceiling"] = (
"Local disposable identity compilation, fresh-profile reconstruction, and cold-process restart only; "
"not a live GatewayRunner, hosted-model, Telegram, production database, VPS restart, or T3 proof."
if positive_restart_passed
else "Local first-process and pre-restart drift-refusal component only; no successful restart proof, "
"GatewayRunner, hosted model, production database, VPS, or T3 claim."
)
stable = {key: value for key, value in report.items() if key != "receipt_sha256"}
report["receipt_sha256"] = behavior.canonical_sha256(stable)
identity.write_json(output, report)
return report, exit_code
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--profile-template", type=Path, required=True)
parser.add_argument("--hermes-root", type=Path, required=True)
parser.add_argument("--deployment-root", type=Path, required=True)
parser.add_argument("--source-root", type=Path, required=True)
parser.add_argument("--database-fingerprint", type=Path, required=True)
parser.add_argument("--constitution", type=Path, required=True)
parser.add_argument("--database-identity", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--inject-drift-before-restart", action="store_true")
args = parser.parse_args()
report, exit_code = run_canary(args)
print(
json.dumps(
{
"status": report.get("status"),
"current_tier": report.get("current_tier"),
"receipt_sha256": report.get("receipt_sha256"),
"output": str(args.output),
},
sort_keys=True,
)
)
return exit_code
if __name__ == "__main__":
raise SystemExit(main())