517 lines
22 KiB
Python
517 lines
22 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, PurePosixPath, PureWindowsPath
|
|
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"
|
|
PRIVATE_PATH_PREFIXES = tuple("/" + value for value in ("Users/", "private/tmp/", "var/folders/"))
|
|
|
|
|
|
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 _receipt_strings(value: object) -> list[str]:
|
|
if isinstance(value, dict):
|
|
keys = [key for key in value if isinstance(key, str)]
|
|
return keys + [text for item in value.values() for text in _receipt_strings(item)]
|
|
if isinstance(value, list):
|
|
return [text for item in value for text in _receipt_strings(item)]
|
|
return [value] if isinstance(value, str) else []
|
|
|
|
|
|
def _validate_portable_receipt(value: object) -> None:
|
|
for text in _receipt_strings(value):
|
|
if (
|
|
any(prefix in text for prefix in PRIVATE_PATH_PREFIXES)
|
|
or PurePosixPath(text).is_absolute()
|
|
or PureWindowsPath(text).is_absolute()
|
|
):
|
|
raise CanaryError("receipt contains a private or absolute filesystem path")
|
|
|
|
|
|
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 _logical_repo_path(path: Path, *, deployment_root: Path, placeholder: str) -> str:
|
|
"""Return a stable repo-relative path or a non-identifying placeholder."""
|
|
|
|
try:
|
|
relative = path.resolve().relative_to(deployment_root.resolve())
|
|
except (OSError, ValueError):
|
|
return placeholder
|
|
value = relative.as_posix()
|
|
return value if value != "." else "."
|
|
|
|
|
|
def _logical_query_command(
|
|
*,
|
|
deployment_root: Path,
|
|
source_root: Path,
|
|
hermes_root: Path,
|
|
) -> list[str]:
|
|
return [
|
|
"<python>",
|
|
"-m",
|
|
"scripts.leo_identity_profile",
|
|
"query",
|
|
"--profile",
|
|
"<temporary-profile>",
|
|
"--source-root",
|
|
_logical_repo_path(source_root, deployment_root=deployment_root, placeholder="<source-root>"),
|
|
"--hermes-root",
|
|
_logical_repo_path(hermes_root, deployment_root=deployment_root, placeholder="<hermes-root>"),
|
|
"--deployment-root",
|
|
".",
|
|
"--query",
|
|
profile_runtime.FIXED_QUERY,
|
|
]
|
|
|
|
|
|
def _run_query_child(
|
|
*,
|
|
deployment_root: Path,
|
|
profile: Path,
|
|
source_root: Path,
|
|
hermes_root: Path,
|
|
profile_role: str,
|
|
timeout_seconds: float = 60,
|
|
) -> dict[str, Any]:
|
|
deployment_root = deployment_root.resolve()
|
|
profile = profile.resolve()
|
|
source_root = source_root.resolve()
|
|
hermes_root = hermes_root.resolve()
|
|
actual_argv = [
|
|
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(
|
|
actual_argv,
|
|
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 {
|
|
"logical_command": _logical_query_command(
|
|
deployment_root=deployment_root,
|
|
source_root=source_root,
|
|
hermes_root=hermes_root,
|
|
),
|
|
"command_serialization": "logical_redacted_v1",
|
|
"profile_role": profile_role,
|
|
"actual_argv_persisted": False,
|
|
"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,
|
|
profile_role="drift_negative",
|
|
)
|
|
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,
|
|
profile_role="first_start",
|
|
)
|
|
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,
|
|
profile_role="pre_restart_drift",
|
|
)
|
|
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,
|
|
profile_role="restart",
|
|
)
|
|
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": "details_redacted",
|
|
"detail_sha256": behavior.sha256_bytes(str(exc).encode("utf-8")),
|
|
}
|
|
)
|
|
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."
|
|
)
|
|
_validate_portable_receipt(report)
|
|
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())
|