teleo-infrastructure/scripts/run_leo_clone_lifecycle_checkpoint.py

1583 lines
72 KiB
Python

#!/usr/bin/env python3
"""Run the no-send Leo proposal lifecycle against an existing disposable clone.
The model receives one staging-only bridge verb. Review and apply remain
harness-owned phases that invoke the existing ``kb_review`` and ``kb_apply``
CLIs. The command never creates or drops the clone, restarts a service, exposes
a delivery adapter, or targets the production container for writes.
"""
from __future__ import annotations
import argparse
import asyncio
import hashlib
import json
import re
import shlex
import subprocess
import sys
import traceback
import uuid
from collections.abc import Iterator
from contextlib import contextmanager
from datetime import datetime, timezone
from pathlib import Path
from types import SimpleNamespace
from typing import Any
HERE = Path(__file__).resolve().parent
REPO_ROOT = HERE.parent
sys.path.insert(0, str(HERE))
import apply_proposal as ap # noqa: E402
import run_approve_claim_clone_canary as guarded # noqa: E402
import run_leo_clone_bound_handler_checkpoint as bound # noqa: E402
SCHEMA = "livingip.leoCloneLifecycleCheckpoint.v1"
STAGE_COMMAND = "stage-lifecycle-claim"
INTERNAL_STAGE_COMMAND = "_stage-lifecycle-claim"
DEFAULT_REVIEW_SECRETS_FILE = guarded.DEFAULT_REVIEW_SECRETS_FILE
DEFAULT_APPLY_SECRETS_FILE = ap.DEFAULT_SECRETS_FILE
DEFAULT_REVIEW_ROLE = "kb_review"
DEFAULT_APPLY_ROLE = ap.DEFAULT_ROLE
REVIEWER_HANDLE = guarded.REVIEWER_HANDLE
REVIEW_NOTE = guarded.REVIEW_NOTE
APPLIED_BY_HANDLE = "kb-apply"
MARKER_RE = re.compile(r"[A-Za-z0-9][A-Za-z0-9_.:-]{7,127}\Z")
APPROVAL_TABLE = "kb_stage.kb_proposal_approvals"
LIFECYCLE_TABLES = (*bound.COUNT_TABLES, APPROVAL_TABLE)
PRODUCTION_TABLES = bound.COUNT_TABLES
READ_ONLY_COMMANDS = frozenset(bound.READ_ONLY_BRIDGE_COMMANDS)
STAGING_COMMANDS = frozenset({STAGE_COMMAND})
LIFECYCLE_STATE_PREFIX = "LIFECYCLE_STATE:"
def new_marker(prefix: str) -> str:
timestamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
return f"{prefix}-{timestamp}-{uuid.uuid4().hex[:12]}"
def _stable_uuid(run_marker: str, label: str) -> str:
return str(uuid.uuid5(uuid.NAMESPACE_URL, f"livingip:leo-clone-lifecycle:{run_marker}:{label}"))
def _json_hash(value: Any) -> str:
return hashlib.sha256(
json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode()
).hexdigest()
def build_lifecycle_fixture(run_marker: str) -> dict[str, Any]:
"""Build one deterministic, narrow, strict approve_claim proposal."""
proposal_id = _stable_uuid(run_marker, "proposal")
claim_id = _stable_uuid(run_marker, "claim")
source_id = _stable_uuid(run_marker, "source")
claim_text = (
f"Lifecycle checkpoint {run_marker}: a staged knowledge change remains non-canonical "
"until an explicit operator review and guarded apply both succeed."
)
source_excerpt = (
f"No-send disposable-clone lifecycle observation for {run_marker}; the harness, not Leo, owns review and apply."
)
source_hash = hashlib.sha256(f"livingip-leo-clone-lifecycle\n{run_marker}\n{source_excerpt}".encode()).hexdigest()
apply_payload = {
"contract_version": 2,
"source_proposal_id": None,
"agent_id": None,
"claims": [
{
"id": claim_id,
"type": "structural",
"text": claim_text,
"status": "open",
"confidence": 1.0,
"tags": ["leo-lifecycle-checkpoint", run_marker],
"created_by": None,
"superseded_by": None,
}
],
"sources": [
{
"id": source_id,
"source_type": "observation",
"url": None,
"storage_path": None,
"excerpt": source_excerpt,
"hash": source_hash,
"created_by": None,
}
],
"evidence": [
{
"claim_id": claim_id,
"source_id": source_id,
"role": "grounds",
"weight": 1.0,
"created_by": None,
}
],
"edges": [],
"reasoning_tools": [],
"normalization_manifest": {
"generator": Path(__file__).name,
"run_marker": run_marker,
"scope": "one_claim_one_source_one_evidence",
},
}
proposal_payload = {
"apply_payload": apply_payload,
"lifecycle_checkpoint": {
"run_marker": run_marker,
"model_authority": "stage_only",
"operator_authority": ["review", "guarded_apply"],
},
}
return {
"run_marker": run_marker,
"proposal_id": proposal_id,
"claim_id": claim_id,
"source_id": source_id,
"source_ref": f"leo-clone-lifecycle:{run_marker}",
"rationale": ("Stage one narrow lifecycle claim for explicit operator review in a disposable clone."),
"apply_payload": apply_payload,
"proposal_payload": proposal_payload,
}
def _proposal_json_sql(proposal_id: str) -> str:
return f"""select jsonb_build_object(
'id', id::text,
'proposal_type', proposal_type,
'status', status,
'channel', channel,
'source_ref', source_ref,
'rationale', rationale,
'payload', payload,
'reviewed_by_handle', reviewed_by_handle,
'reviewed_by_agent_id', reviewed_by_agent_id::text,
'reviewed_at', reviewed_at::text,
'review_note', review_note,
'applied_by_handle', applied_by_handle,
'applied_by_agent_id', applied_by_agent_id::text,
'applied_at', applied_at::text
) from kb_stage.kb_proposals where id = {ap.sql_literal(proposal_id)}::uuid"""
def build_stage_sql(fixture: dict[str, Any]) -> str:
"""Build an idempotent staging-only statement; it never touches public.*."""
proposal_id = ap.sql_literal(fixture["proposal_id"])
source_ref = ap.sql_literal(fixture["source_ref"])
rationale = ap.sql_literal(fixture["rationale"])
payload = ap.sql_literal(json.dumps(fixture["proposal_payload"], sort_keys=True))
proposal_select = _proposal_json_sql(fixture["proposal_id"])
return f"""\\set ON_ERROR_STOP on
begin;
create temporary table lifecycle_stage_result (created boolean not null) on commit drop;
with inserted as (
insert into kb_stage.kb_proposals
(id, proposal_type, status, channel, source_ref, rationale, payload)
values
({proposal_id}::uuid, 'approve_claim', 'pending_review', 'clone_lifecycle',
{source_ref}, {rationale}, {payload}::jsonb)
on conflict (id) do nothing
returning id
)
insert into lifecycle_stage_result(created)
select exists(select 1 from inserted);
do $lifecycle$
declare
marker_count integer;
exact_count integer;
begin
select count(*) into marker_count
from kb_stage.kb_proposals
where source_ref = {source_ref};
select count(*) into exact_count
from kb_stage.kb_proposals
where id = {proposal_id}::uuid
and proposal_type = 'approve_claim'
and status = 'pending_review'
and channel = 'clone_lifecycle'
and source_ref = {source_ref}
and rationale = {rationale}
and payload = {payload}::jsonb
and reviewed_by_handle is null
and reviewed_by_agent_id is null
and reviewed_at is null
and review_note is null
and applied_by_handle is null
and applied_by_agent_id is null
and applied_at is null;
if marker_count <> 1 or exact_count <> 1 then
raise exception 'lifecycle stage validation failed: marker_count=%, exact_count=%',
marker_count, exact_count;
end if;
end
$lifecycle$;
select jsonb_build_object(
'created', (select created from lifecycle_stage_result),
'marker_match_count', (
select count(*) from kb_stage.kb_proposals where source_ref = {source_ref}
),
'proposal', ({proposal_select})
)::text;
commit;
"""
def target_unrelated_guard_snapshot(container: str, database: str, fixture: dict[str, Any]) -> dict[str, Any]:
"""Fingerprint all lifecycle-table rows except this run's deterministic rows."""
predicates = {
"public.claims": f"t.id <> {ap.sql_literal(fixture['claim_id'])}::uuid",
"public.sources": f"t.id <> {ap.sql_literal(fixture['source_id'])}::uuid",
"public.claim_evidence": (
"not ("
f"t.claim_id = {ap.sql_literal(fixture['claim_id'])}::uuid and "
f"t.source_id = {ap.sql_literal(fixture['source_id'])}::uuid and "
"t.role::text = 'grounds')"
),
"public.claim_edges": "true",
"public.reasoning_tools": "true",
"kb_stage.kb_proposals": f"t.id <> {ap.sql_literal(fixture['proposal_id'])}::uuid",
APPROVAL_TABLE: f"t.proposal_id <> {ap.sql_literal(fixture['proposal_id'])}::uuid",
}
pairs = []
for table in LIFECYCLE_TABLES:
predicate = predicates[table]
pairs.append(
f"""'{table}', jsonb_build_object(
'count', (select count(*) from {table} t where {predicate}),
'rowset_md5', (select md5(coalesce(string_agg(to_jsonb(t)::text, E'\\n'
order by to_jsonb(t)::text), '')) from {table} t where {predicate})
)"""
)
return bound._psql_json(
container,
database,
"""\\set ON_ERROR_STOP on
begin transaction read only;
select jsonb_build_object(
"""
+ ",\n ".join(pairs)
+ """
)::text;
rollback;
""",
)
def _validate_marker(marker: str, flag: str) -> None:
if not MARKER_RE.fullmatch(marker):
raise bound.CheckpointError(
f"{flag} must be 8-128 characters using only letters, digits, '.', '_', ':', or '-'"
)
def assert_disposable_target(container: str, database: str) -> tuple[dict[str, Any], dict[str, Any]]:
if not bound.SAFE_DOCKER_NAME_RE.fullmatch(container):
raise bound.CheckpointError("--container must be an explicit Docker name")
if container == bound.PRODUCTION_CONTAINER:
raise bound.CheckpointError("--container must not target the production teleo-pg container")
if not bound.SAFE_DB_NAME_RE.fullmatch(database):
raise bound.CheckpointError("--db must be an explicit Postgres database name")
target = bound.container_identity(container)
production = bound.container_identity(bound.PRODUCTION_CONTAINER)
if target["id"] == production["id"]:
raise bound.CheckpointError("supplied target resolves to the production container identity")
bound.validate_disposable_target_identity(target, production)
return target, production
def stage_lifecycle_proposal(container: str, database: str, fixture: dict[str, Any]) -> dict[str, Any]:
"""Stage or rediscover the exact deterministic proposal in the clone."""
assert_disposable_target(container, database)
result = bound._psql_json(container, database, build_stage_sql(fixture))
proposal = result.get("proposal") if isinstance(result, dict) else None
if not proposal:
raise bound.CheckpointError("staging command returned no proposal")
expected = {
"id": fixture["proposal_id"],
"proposal_type": "approve_claim",
"status": "pending_review",
"channel": "clone_lifecycle",
"source_ref": fixture["source_ref"],
"rationale": fixture["rationale"],
"payload": fixture["proposal_payload"],
}
mismatches = {
key: {"expected": value, "actual": proposal.get(key)}
for key, value in expected.items()
if proposal.get(key) != value
}
if mismatches:
raise bound.CheckpointError(
"deterministic lifecycle proposal already exists with different state or content: "
+ json.dumps(mismatches, sort_keys=True)
)
if result.get("marker_match_count") != 1:
raise bound.CheckpointError("run marker did not resolve to exactly one staged proposal")
return {
"created": result.get("created") is True,
"idempotent_existing": result.get("created") is False,
"marker_match_count": result.get("marker_match_count"),
"proposal": proposal,
"canonical_row_ids": {
"public.claims": [fixture["claim_id"]],
"public.sources": [fixture["source_id"]],
"public.claim_evidence": [
{
"claim_id": fixture["claim_id"],
"source_id": fixture["source_id"],
"role": "grounds",
}
],
},
}
def build_lifecycle_wrapper(
*,
kb_tool: Path,
tool_log: Path,
container: str,
database: str,
run_marker: str,
run_nonce: str,
) -> str:
script = Path(__file__).resolve()
python = Path(sys.executable).resolve()
return f"""#!/bin/bash
set -uo pipefail
KB_TOOL={shlex.quote(str(kb_tool))}
TOOL_LOG={shlex.quote(str(tool_log))}
TARGET_CONTAINER={shlex.quote(container)}
TARGET_DATABASE={shlex.quote(database)}
LIFECYCLE_SCRIPT={shlex.quote(str(script))}
PYTHON={shlex.quote(str(python))}
DOCKER={shlex.quote(bound.SYSTEM_DOCKER)}
export PATH={shlex.quote(bound.SYSTEM_EXEC_PATH)}
RUN_MARKER={shlex.quote(run_marker)}
RUN_NONCE={shlex.quote(run_nonce)}
INVOCATION_ID="$($PYTHON -c 'import uuid; print(uuid.uuid4())')"
DB_RECEIPT="$($DOCKER exec "$TARGET_CONTAINER" psql -U postgres -d "$TARGET_DATABASE" -At -q -v ON_ERROR_STOP=1 -c "select jsonb_build_object('current_database', current_database(), 'system_identifier', (select system_identifier::text from pg_control_system()), 'transaction_read_only', current_setting('transaction_read_only'))::text")"
if [[ -z "$DB_RECEIPT" ]]; then
exit 125
fi
$PYTHON - "$TOOL_LOG" "$RUN_NONCE" "$INVOCATION_ID" "$TARGET_CONTAINER" "$TARGET_DATABASE" "$DB_RECEIPT" "$@" <<'PY'
import json
import sys
from datetime import datetime, timezone
path, run_nonce, invocation_id, container, database, db_receipt, *argv = sys.argv[1:]
with open(path, "a", encoding="utf-8") as handle:
handle.write(json.dumps({{
"phase": "start",
"at_utc": datetime.now(timezone.utc).isoformat(),
"invocation_id": invocation_id,
"run_nonce": run_nonce,
"container": container,
"database": database,
"database_identity": json.loads(db_receipt),
"argv": argv,
}}, sort_keys=True) + "\\n")
PY
if [[ "${{1:-}}" == {shlex.quote(STAGE_COMMAND)} ]]; then
if [[ "$#" -ne 1 ]]; then
printf '%s\n' '{STAGE_COMMAND} accepts no model-supplied arguments' >&2
STATUS=64
else
"$PYTHON" "$LIFECYCLE_SCRIPT" {shlex.quote(INTERNAL_STAGE_COMMAND)} \
--container "$TARGET_CONTAINER" --db "$TARGET_DATABASE" --run-marker "$RUN_MARKER"
STATUS=$?
fi
else
"$PYTHON" "$KB_TOOL" --local --container "$TARGET_CONTAINER" --db "$TARGET_DATABASE" "$@"
STATUS=$?
fi
$PYTHON - "$TOOL_LOG" "$RUN_NONCE" "$INVOCATION_ID" "$TARGET_CONTAINER" "$TARGET_DATABASE" "$STATUS" <<'PY'
import json
import sys
from datetime import datetime, timezone
path, run_nonce, invocation_id, container, database, status = sys.argv[1:]
with open(path, "a", encoding="utf-8") as handle:
handle.write(json.dumps({{
"phase": "end",
"at_utc": datetime.now(timezone.utc).isoformat(),
"invocation_id": invocation_id,
"run_nonce": run_nonce,
"container": container,
"database": database,
"returncode": int(status),
}}, sort_keys=True) + "\\n")
PY
exit "$STATUS"
"""
def patch_lifecycle_bridge(
temp_profile: Path,
*,
container: str,
database: str,
fixture: dict[str, Any],
) -> dict[str, Any]:
bridge = bound.patch_temp_bridge(temp_profile, container, database)
wrapper = Path(bridge["wrapper_path"])
kb_tool = temp_profile / "bin" / "kb_tool.py"
tool_log = Path(bridge["tool_log_path"])
skill_path = Path(bridge["bridge_skill_path"])
wrapper_text = build_lifecycle_wrapper(
kb_tool=kb_tool,
tool_log=tool_log,
container=container,
database=database,
run_marker=fixture["run_marker"],
run_nonce=bridge["run_nonce"],
)
skill_text = skill_path.read_text(encoding="utf-8")
skill_text = skill_text.replace(
"""End the final answer with one machine-readable line using the full proposal
UUID and the row state you observed:
`KB_STATE: {\"proposal_id\":\"<uuid>\",\"status\":\"pending_review|approved|applied\",\"applied\":false}`
""",
"",
)
skill_text = skill_text.replace(
"This checkpoint exposes\nonly read-only bridge verbs and records every invocation in its receipt.",
"This checkpoint exposes read-only bridge verbs plus the single staging-only verb documented above, "
"and records every invocation in its receipt.",
)
lifecycle_binding = f"""
## Disposable Lifecycle Staging Authority
This no-send profile may make exactly one kind of write, only in the supplied
disposable clone: `{wrapper} {STAGE_COMMAND}`. The command accepts no arguments
and stages one deterministic `approve_claim` row as `pending_review` for run
marker `{fixture["run_marker"]}`. Use it when the operator asks for the narrowest
reviewable change, then read the returned proposal with `show-proposal`.
You cannot approve or apply proposals. Do not claim that a staged or approved
proposal is canonical. Only the external harness may invoke the separate
`kb_review` and `kb_apply` paths after your turn has ended.
Each prompt defines one exact `LIFECYCLE_STATE:` JSON receipt. Put that receipt
on the final line of the answer, using full UUIDs and values actually observed
from the clone. Never substitute the generic `KB_STATE:` receipt in this
lifecycle checkpoint.
"""
skill_text = bound.inject_skill_binding(skill_text, lifecycle_binding.lstrip())
bound._detach_and_write(wrapper, wrapper_text, mode=0o700)
bound._detach_and_write(skill_path, skill_text, mode=0o600)
bridge.update(
{
"wrapper_sha256": bound.sha256_bytes(wrapper_text.encode()),
"bridge_skill_sha256": bound.sha256_bytes(skill_text.encode()),
"staging_command": STAGE_COMMAND,
"staging_command_accepts_model_arguments": False,
"staging_target_is_hard_bound": True,
"model_can_approve": False,
"model_can_apply": False,
}
)
return bridge
@contextmanager
def lifecycle_gateway_surface(*, allow_staging: bool) -> Iterator[None]:
"""Expose the staging verb only for the one explicitly authorized turn."""
original_commands = bound.READ_ONLY_BRIDGE_COMMANDS
original_install = bound.install_checkpoint_tool_surface
original_validator = bound.validate_read_only_bridge_argv
def install(temp_profile: Path) -> dict[str, Any]:
surface = original_install(temp_profile)
surface.update(
{
"read_only_bridge_commands": sorted(READ_ONLY_COMMANDS),
"staging_bridge_commands": sorted(STAGING_COMMANDS) if allow_staging else [],
"model_can_stage_pending_proposal": allow_staging,
"model_can_approve_or_apply": False,
"operator_review_apply_tools_exposed": False,
}
)
return surface
def validate(argv: list[str]) -> None:
if allow_staging and argv == [STAGE_COMMAND]:
return
original_validator(argv)
bound.READ_ONLY_BRIDGE_COMMANDS = frozenset(
READ_ONLY_COMMANDS | STAGING_COMMANDS if allow_staging else READ_ONLY_COMMANDS
)
bound.install_checkpoint_tool_surface = install
bound.validate_read_only_bridge_argv = validate
try:
yield
finally:
bound.READ_ONLY_BRIDGE_COMMANDS = original_commands
bound.install_checkpoint_tool_surface = original_install
bound.validate_read_only_bridge_argv = original_validator
def lifecycle_prompts(fixture: dict[str, Any], conversation_marker: str) -> dict[str, str]:
proposal_id = fixture["proposal_id"]
claim_id = fixture["claim_id"]
source_id = fixture["source_id"]
return {
"T1_conversation_marker": (
"Remember this exact conversation-only marker for a later turn: "
f"{conversation_marker}. Reply with the exact marker and say that remembering it does not change "
"the canonical Postgres KB. Do not stage anything yet. End with exactly: "
f'{LIFECYCLE_STATE_PREFIX} {{"phase":"T1","conversation_marker":"{conversation_marker}",'
'"kb_mutated":false}'
),
"T2_stage_pending_proposal": (
"Cory-style request: get this into Leo now - every staged knowledge change must remain non-canonical "
"until an operator reviews it and a guarded apply succeeds. Make the narrowest reviewable claim change, "
f"tag this run with {fixture['run_marker']}, do not approve or apply it, and report the proposal ID and "
f'state. End with exactly: {LIFECYCLE_STATE_PREFIX} {{"phase":"T2","proposal_id":"{proposal_id}",'
'"status":"pending_review","canonical":false}'
),
"T3_approved_unapplied_readback": (
f"Read proposal {proposal_id} from the clone now. Tell me its exact status, whether applied_at is NULL, "
"and whether the planned claim is already canonical. Do not stage another proposal and do not apply it. "
f'End with exactly: {LIFECYCLE_STATE_PREFIX} {{"phase":"T3","proposal_id":"{proposal_id}",'
'"status":"approved","applied":false,"canonical":false}'
),
"T5_recall_and_applied_readback": (
"The isolated handler has been reopened after the harness completed guarded apply. Without asking me to "
f"repeat the conversation-only marker, recall it exactly. Then show proposal {proposal_id}, show canonical "
f"claim {claim_id}, and report the exact proposal, claim, and source row IDs (source {source_id}) plus the "
f'proposal status. End with exactly: {LIFECYCLE_STATE_PREFIX} {{"phase":"T5",'
f'"conversation_marker":"<recalled exact marker>","proposal_id":"{proposal_id}",'
f'"status":"applied","claim_id":"{claim_id}","source_id":"{source_id}"}}'
),
}
def _turn_args(args: argparse.Namespace, phase: str, prompt: str) -> argparse.Namespace:
return SimpleNamespace(
chat_id=args.chat_id,
user_id=args.user_id,
user_name=args.user_name,
prompt=prompt,
prompt_id=phase,
run_id=args.run_marker,
turn_timeout=args.turn_timeout,
)
async def run_gateway_turn(
args: argparse.Namespace,
temp_profile: Path,
*,
phase: str,
prompt: str,
provider_environment: dict[str, str],
tool_log: Path,
) -> dict[str, Any]:
proof_args = {
"run_nonce": args.tool_run_nonce,
"database_identity": args.target_database_identity,
"require_database_read_only": False,
}
before = bound.read_tool_proof(tool_log, args.bound_container_id, args.db, **proof_args)
with lifecycle_gateway_surface(allow_staging=phase == "T2_stage_pending_proposal"):
gateway = await bound.invoke_gateway_subprocess(
_turn_args(args, phase, prompt),
temp_profile,
provider_environment=provider_environment,
)
after = bound.read_tool_proof(tool_log, args.bound_container_id, args.db, **proof_args)
new_invocations = after["invocations"][before["invocation_count"] :]
return {
"phase": phase,
"prompt": prompt,
"prompt_sha256": hashlib.sha256(prompt.encode()).hexdigest(),
"gateway": gateway,
"tool_invocations": new_invocations,
}
def _phase_commands(turn: dict[str, Any]) -> list[str]:
return [
str(invocation.get("argv", [None])[0])
for invocation in turn.get("tool_invocations", [])
if invocation.get("argv")
]
def _phase_argvs(turn: dict[str, Any]) -> list[list[str]]:
return [
[str(value) for value in invocation.get("argv", [])]
for invocation in turn.get("tool_invocations", [])
if invocation.get("argv")
]
def _phase_has_bound_read(turn: dict[str, Any], command: str, row_id: str) -> bool:
expected = [command, row_id]
return any(
argv == expected or (argv[:2] == expected and argv[2:] in (["--format", "json"], ["--format", "markdown"]))
for argv in _phase_argvs(turn)
)
def _require_gateway_turn(turn: dict[str, Any]) -> None:
gateway = turn.get("gateway") or {}
if gateway.get("handler_error"):
raise bound.CheckpointError(f"{turn['phase']} handler failed: {gateway['handler_error']}")
if gateway.get("authorized") is not True or gateway.get("handler_invoked") is not True:
raise bound.CheckpointError(f"{turn['phase']} did not invoke an authorized GatewayRunner handler")
if not str(gateway.get("reply") or "").strip():
raise bound.CheckpointError(f"{turn['phase']} returned an empty reply")
def _command_receipt(result: subprocess.CompletedProcess[str]) -> dict[str, Any]:
stdout = bound.redact_text(result.stdout or "")
stderr = bound.redact_text(result.stderr or "")
return {
"returncode": result.returncode,
"stdout_sha256": hashlib.sha256(stdout.encode()).hexdigest(),
"stderr_sha256": hashlib.sha256(stderr.encode()).hexdigest(),
"stdout_excerpt": stdout[:2000],
"stderr_excerpt": stderr[:2000],
"stdout_truncated": len(stdout) > 2000,
"stderr_truncated": len(stderr) > 2000,
}
def _guarded_args(args: argparse.Namespace) -> argparse.Namespace:
return SimpleNamespace(
container=args.bound_container_id,
approve_script=HERE / "approve_proposal.py",
apply_script=HERE / "apply_proposal.py",
review_secrets_file=args.review_secrets_file,
secrets_file=args.apply_secrets_file,
review_role=DEFAULT_REVIEW_ROLE,
apply_role=DEFAULT_APPLY_ROLE,
)
def run_operator_review(
args: argparse.Namespace, proposal_id: str
) -> tuple[subprocess.CompletedProcess[str], subprocess.CompletedProcess[str]]:
guard_args = _guarded_args(args)
dry_run = guarded._approve(guard_args, proposal_id, args.db, dry_run=True)
if dry_run.returncode != 0 or "kb_stage.approve_strict_proposal" not in dry_run.stdout:
raise bound.CheckpointError(
"operator review dry-run did not build the payload-bound approval function: "
+ bound.redact_text(dry_run.stderr or dry_run.stdout)
)
applied = guarded._approve(guard_args, proposal_id, args.db)
if applied.returncode != 0:
raise bound.CheckpointError("operator review failed: " + bound.redact_text(applied.stderr or applied.stdout))
return dry_run, applied
def run_guarded_apply(
args: argparse.Namespace, proposal_id: str
) -> tuple[subprocess.CompletedProcess[str], subprocess.CompletedProcess[str]]:
guard_args = _guarded_args(args)
dry_run = guarded._apply(guard_args, proposal_id, args.db, dry_run=True)
required_signals = ("kb_stage.assert_approved_proposal", "kb_stage.finish_approved_proposal")
if dry_run.returncode != 0 or not all(signal in dry_run.stdout for signal in required_signals):
raise bound.CheckpointError(
"guarded apply dry-run did not build both payload-bound apply guards: "
+ bound.redact_text(dry_run.stderr or dry_run.stdout)
)
applied = guarded._apply(guard_args, proposal_id, args.db)
if applied.returncode != 0:
raise bound.CheckpointError("guarded apply failed: " + bound.redact_text(applied.stderr or applied.stdout))
return dry_run, applied
def _table_deltas(before: dict[str, int], after: dict[str, int]) -> dict[str, int]:
return guarded._table_deltas(before, after)
def _expected_deltas(fixture: dict[str, Any]) -> tuple[dict[str, int], dict[str, int]]:
canonical = guarded._expected_table_deltas(guarded._expected_bundle_rows(fixture["apply_payload"]))
canonical[APPROVAL_TABLE] = 0
from_baseline = dict(canonical)
from_baseline["kb_stage.kb_proposals"] = 1
from_baseline[APPROVAL_TABLE] = 1
return canonical, from_baseline
def _snapshot_matches_production(target: dict[str, Any] | None, production: dict[str, Any] | None) -> bool:
if not target or not production:
return False
return all(
target.get(section, {}).get(table) == production.get(section, {}).get(table)
for section in ("counts", "rowset_md5")
for table in PRODUCTION_TABLES
)
def _service_unchanged(before: dict[str, Any] | None, after: dict[str, Any] | None) -> bool:
return bool(before and after and before.get("returncode") == 0 and before == after)
def _reply_mentions(reply: str, value: str) -> bool:
lowered = reply.lower()
value = value.lower()
return value in lowered or value[:8] in lowered
def parse_lifecycle_state(reply: str) -> dict[str, Any]:
for line in reversed(reply.splitlines()):
stripped = line.strip()
if not stripped.startswith(LIFECYCLE_STATE_PREFIX):
continue
payload = stripped[len(LIFECYCLE_STATE_PREFIX) :].strip()
try:
value = json.loads(payload)
except json.JSONDecodeError as exc:
return {"valid": False, "error": f"invalid lifecycle JSON: {exc}"}
if not isinstance(value, dict):
return {"valid": False, "error": "lifecycle receipt must be a JSON object"}
if value.get("phase") not in {"T1", "T2", "T3", "T5"}:
return {"valid": False, "error": "lifecycle receipt phase is invalid"}
return {"valid": True, "value": value}
return {"valid": False, "error": "reply did not contain a LIFECYCLE_STATE line"}
def lifecycle_state_matches(reply: str, expected: dict[str, Any]) -> bool:
receipt = parse_lifecycle_state(reply)
return receipt.get("valid") is True and receipt.get("value") == expected
def _reply_has_phase_contradiction(phase: str, reply: str) -> bool:
prose = "\n".join(
line for line in reply.lower().splitlines() if not line.strip().startswith(LIFECYCLE_STATE_PREFIX.lower())
)
forbidden = {
"T1": ("staged a proposal", "canonical kb changed", "kb was mutated"),
"T2": ("already canonical", "now canonical", "became canonical", "status is approved", "status is applied"),
"T3": ("already canonical", "now canonical", "became canonical", "status is pending", "has been applied"),
"T5": ("not canonical", "not applied", "status is pending", "status is approved"),
}
return any(fragment in prose for fragment in forbidden[phase])
def _all_turns(report: dict[str, Any]) -> list[dict[str, Any]]:
return [
report.get("turns", {}).get(name, {})
for name in (
"T1_conversation_marker",
"T2_stage_pending_proposal",
"T3_approved_unapplied_readback",
"T5_recall_and_applied_readback",
)
]
def evaluate_checks(report: dict[str, Any], args: argparse.Namespace, fixture: dict[str, Any]) -> dict[str, bool]:
turns = _all_turns(report)
gateways = [turn.get("gateway") or {} for turn in turns]
replies = [str(gateway.get("reply") or "") for gateway in gateways]
tool_surfaces = [gateway.get("tool_surface") or {} for gateway in gateways]
children = [gateway.get("child_process") or {} for gateway in gateways]
terminal_attempts = [
gateway.get("transcript_terminal_attempts")
or bound.transcript_terminal_attempt_summary((gateway.get("transcript_tool_trace") or {}).get("events", []))
for gateway in gateways
]
transcript_calls = [
event.get("tool_name")
for gateway in gateways
for event in (gateway.get("transcript_tool_trace") or {}).get("events", [])
if event.get("phase") == "call"
]
allowed_tool_names = {name for surface in tool_surfaces for name in (surface.get("allowed_tools") or [])}
all_commands = [command for turn in turns for command in _phase_commands(turn)]
pending = report.get("pending_readback")
approved = report.get("approved_unapplied_readback")
applied = report.get("final_applied_readback")
expected_rows = report.get("expected_canonical_rows")
canonical_rows = report.get("final_canonical_rows")
production = report.get("production_invariants") or {}
cleanup = report.get("cleanup") or {}
restart = report.get("isolated_restart") or {}
operator_review = report.get("operator_review") or {}
guarded_apply = report.get("guarded_apply") or {}
target_deltas = report.get("target_deltas") or {}
expected_apply_delta, expected_final_delta = _expected_deltas(fixture)
expected_stage_delta = {table: 0 for table in LIFECYCLE_TABLES}
expected_stage_delta["kb_stage.kb_proposals"] = 1
expected_review_delta = {table: 0 for table in LIFECYCLE_TABLES}
expected_review_delta[APPROVAL_TABLE] = 1
t3_lower = replies[2].lower() if len(replies) > 2 else ""
t5_lower = replies[3].lower() if len(replies) > 3 else ""
expected_receipts = [
{"phase": "T1", "conversation_marker": args.conversation_marker, "kb_mutated": False},
{
"phase": "T2",
"proposal_id": fixture["proposal_id"],
"status": "pending_review",
"canonical": False,
},
{
"phase": "T3",
"proposal_id": fixture["proposal_id"],
"status": "approved",
"applied": False,
"canonical": False,
},
{
"phase": "T5",
"conversation_marker": args.conversation_marker,
"proposal_id": fixture["proposal_id"],
"status": "applied",
"claim_id": fixture["claim_id"],
"source_id": fixture["source_id"],
},
]
target = report.get("target") or {}
target_before = target.get("container_identity_before") or {}
target_after = target.get("container_identity_after") or {}
target_guard_before = report.get("target_guard_snapshot_before") or {}
target_guard_after = report.get("target_guard_snapshot_after") or {}
return {
"target_container_identity_is_not_production": (
bool(target_before.get("id"))
and target_before.get("id") != production.get("container_identity", {}).get("id")
and args.container != bound.PRODUCTION_CONTAINER
),
"target_container_isolation_contract_passed": bool(target.get("isolation_checks"))
and all(target.get("isolation_checks", {}).values()),
"target_container_name_still_resolves_to_pinned_identity": bool(target_after)
and target_after == target_before
and target.get("bound_container_id") == target_before.get("id"),
"target_postgres_system_is_distinct_and_stable": bool(target_guard_before and target_guard_after)
and target_guard_before.get("database_identity", {}).get("system_identifier")
!= production.get("guard_snapshot_before", {}).get("database_identity", {}).get("system_identifier")
and target_guard_before.get("database_identity", {}).get("system_identifier")
== target_guard_after.get("database_identity", {}).get("system_identifier")
and target_guard_after.get("database_identity", {}).get("current_database") == args.db,
"clone_baseline_matches_full_production_data": report.get("clone_baseline_matches_production") is True,
"all_gateway_turns_authorized_and_nonempty": bool(gateways)
and all(
gateway.get("authorized") is True
and gateway.get("handler_invoked") is True
and not gateway.get("handler_error")
and bool(str(gateway.get("reply") or "").strip())
for gateway in gateways
),
"T1_marker_acknowledged_as_conversation_only": (
args.conversation_marker in replies[0] and "canonical" in replies[0].lower() if replies else False
),
"T1_database_unchanged_and_staging_absent": report.get("target_guard_snapshot_after_t1")
== report.get("target_guard_snapshot_before")
and report.get("T1_proposal_readback") is None
and STAGE_COMMAND not in (_phase_commands(turns[0]) if turns else []),
"all_lifecycle_state_receipts_exact": len(replies) == len(expected_receipts)
and all(
lifecycle_state_matches(reply, expected) for reply, expected in zip(replies, expected_receipts, strict=True)
),
"no_lifecycle_reply_contradicts_its_receipt": len(replies) == len(expected_receipts)
and all(
not _reply_has_phase_contradiction(phase, reply)
for phase, reply in zip(("T1", "T2", "T3", "T5"), replies, strict=True)
),
"T2_model_invoked_exact_staging_verb": [STAGE_COMMAND] in _phase_argvs(turns[1]),
"T2_model_read_exact_staged_proposal": _phase_has_bound_read(turns[1], "show-proposal", fixture["proposal_id"]),
"model_never_invoked_review_or_apply": all(
not re.search(r"(?:^|[-_])(approve|apply)(?:$|[-_])", command) for command in all_commands
),
"all_bridge_invocations_within_read_or_stage_allowlist": bool(all_commands)
and all(command in READ_ONLY_COMMANDS | STAGING_COMMANDS for command in all_commands),
"all_bridge_invocations_bound_and_successful": (
report.get("tool_proof", {}).get("all_bound_to_supplied_target") is True
and report.get("tool_proof", {}).get("all_completed_successfully") is True
),
"pending_proposal_exact_and_unreviewed": (
pending is not None
and pending.get("id") == fixture["proposal_id"]
and pending.get("payload") == fixture["proposal_payload"]
and bound._state_semantics(pending, "pending_review")["all"]
),
"pending_state_has_no_canonical_rows": report.get("pending_canonical_rows")
== {key: [] for key in guarded._expected_bundle_rows(fixture["apply_payload"])},
"staging_idempotently_rediscovered_one_proposal": (
report.get("staging_idempotency_replay", {}).get("idempotent_existing") is True
and report.get("staging_idempotency_replay", {}).get("marker_match_count") == 1
and report.get("staging_idempotency_replay", {}).get("proposal", {}).get("id") == fixture["proposal_id"]
),
"operator_review_used_payload_bound_security_definer": (
operator_review.get("dry_run", {}).get("returncode") == 0
and operator_review.get("dry_run_uses_approve_strict_proposal") is True
and operator_review.get("apply", {}).get("returncode") == 0
),
"approved_but_unapplied_readback_exact": (
guarded._approval_transition_valid(pending, approved)
and bound._state_semantics(approved or {}, "approved")["all"]
and report.get("approved_canonical_rows")
== {key: [] for key in guarded._expected_bundle_rows(fixture["apply_payload"])}
),
"immutable_operator_approval_matches_ledger": guarded._approval_snapshot_matches(
approved, report.get("immutable_approval_readback")
),
"T3_handler_read_approved_but_unapplied_state": (
_phase_has_bound_read(turns[2], "show-proposal", fixture["proposal_id"])
and _reply_mentions(replies[2], fixture["proposal_id"])
and "approved" in t3_lower
and (
"not applied" in t3_lower
or "not canonical" in t3_lower
or ("applied_at" in t3_lower and "null" in t3_lower)
)
),
"guarded_apply_used_both_payload_guards": (
guarded_apply.get("dry_run", {}).get("returncode") == 0
and guarded_apply.get("dry_run_uses_assert_approved_proposal") is True
and guarded_apply.get("dry_run_uses_finish_approved_proposal") is True
and guarded_apply.get("apply", {}).get("returncode") == 0
),
"apply_transition_exact": guarded._apply_transition_valid(approved, applied),
"final_canonical_rows_exact": canonical_rows == expected_rows,
"staging_table_deltas_exact": target_deltas.get("baseline_to_stage") == expected_stage_delta,
"review_created_only_immutable_approval_row": target_deltas.get("stage_to_approval") == expected_review_delta,
"approval_snapshot_unchanged_during_apply": report.get("immutable_approval_readback")
== report.get("immutable_approval_readback_after_apply"),
"apply_table_deltas_exact": target_deltas.get("approved_to_applied") == expected_apply_delta,
"full_lifecycle_table_deltas_exact": target_deltas.get("baseline_to_final") == expected_final_delta,
"all_unrelated_clone_rows_unchanged": report.get("target_unrelated_rows_unchanged") is True,
"isolated_handler_reopened_with_same_session": (
restart.get("prior_child_absent_before_reopen") is True
and restart.get("new_child_started") is True
and restart.get("same_session_key") is True
and restart.get("same_persisted_session_id") is True
and restart.get("service_restart_performed") is False
),
"T5_prompt_did_not_repeat_conversation_marker": (
args.conversation_marker not in (turns[3].get("prompt") or "")
and args.conversation_marker not in json.dumps(fixture, sort_keys=True)
),
"T5_recalled_marker_and_applied_rows": (
args.conversation_marker in replies[3]
and "applied" in t5_lower
and _reply_mentions(replies[3], fixture["proposal_id"])
and _reply_mentions(replies[3], fixture["claim_id"])
and _phase_has_bound_read(turns[3], "show-proposal", fixture["proposal_id"])
and _phase_has_bound_read(turns[3], "show", fixture["claim_id"])
),
"send_tool_and_delivery_adapters_absent": bool(tool_surfaces)
and all(
surface.get("send_message_tool_enabled") is False
and set(surface.get("allowed_tools") or []) == {"skills_list", "skill_view", "terminal"}
and set(surface.get("actual_registry_tools") or []) == {"skills_list", "skill_view", "terminal"}
and surface.get("gateway_adapters_verified_mapping") is True
and surface.get("gateway_adapter_count") == 0
and surface.get("model_can_approve_or_apply") is False
and surface.get("operator_review_apply_tools_exposed") is False
for surface in tool_surfaces
),
"all_transcript_tool_calls_allowlisted": bool(transcript_calls)
and all(name in allowed_tool_names for name in transcript_calls),
"all_gateway_process_groups_removed": bool(children)
and all(
child.get("alive_after_readback") is False and child.get("process_group_alive_after_readback") is False
for child in children
),
"all_gateway_children_ready_and_cleanly_exited": bool(children)
and all(
child.get("readiness_verified") is True
and child.get("timed_out") is False
and child.get("exitcode") == 0
and (child.get("termination") or {}).get("attempted") is False
for child in children
),
"all_gateway_results_used_private_files": bool(children)
and all(child.get("result_transport") == "private_temp_file" for child in children),
"all_terminal_calls_passed_first_time": bool(terminal_attempts)
and all(
attempt.get("rejected_call_count") == 0
and attempt.get("nonzero_call_count") == 0
and attempt.get("result_code_unknown_call_count") == 0
for attempt in terminal_attempts
)
and sum(int(attempt.get("call_count") or 0) for attempt in terminal_attempts)
== report.get("tool_proof", {}).get("invocation_count"),
"production_row_fingerprints_unchanged": production.get("guard_snapshot_unchanged") is True,
"production_service_unchanged": production.get("service_unchanged") is True,
"live_bridge_unchanged": production.get("live_bridge_unchanged") is True,
"source_files_unchanged_during_run": report.get("source_files_unchanged_during_run") is True,
"no_telegram_send": report.get("posted_to_telegram") is False
and all(gateway.get("posted_to_telegram") is False for gateway in gateways),
"temporary_profile_and_session_removed": (
cleanup.get("temp_profile_removed") is True
and cleanup.get("temp_session_removed_with_profile") is True
and cleanup.get("absence_verified_independently") is True
and cleanup.get("active_temp_root_registry_clear") is True
and cleanup.get("active_gateway_registry_clear") is True
),
}
def validate_args(args: argparse.Namespace) -> None:
_validate_marker(args.run_marker, "--run-marker")
_validate_marker(args.conversation_marker, "--conversation-marker")
if args.run_marker == args.conversation_marker:
raise bound.CheckpointError("run and conversation markers must be distinct")
if not bound.SAFE_DOCKER_NAME_RE.fullmatch(args.container):
raise bound.CheckpointError("--container must be an explicit Docker name")
if args.container == bound.PRODUCTION_CONTAINER:
raise bound.CheckpointError("--container must not target the production teleo-pg container")
if not bound.SAFE_DB_NAME_RE.fullmatch(args.db):
raise bound.CheckpointError("--db must be an explicit Postgres database name")
if args.turn_timeout <= 0:
raise bound.CheckpointError("--turn-timeout must be positive")
if not args.operator_review:
raise bound.CheckpointError("--operator-review is required for the explicit harness review phase")
if not args.guarded_apply:
raise bound.CheckpointError("--guarded-apply is required for the clone-only apply phase")
if not args.copy_model_auth:
raise bound.CheckpointError("--copy-model-auth is required for the isolated live GatewayRunner turns")
args.output = bound.validate_private_output_path(args.output)
def _source_manifest() -> list[dict[str, Any]]:
records = []
for path in (
Path(__file__).resolve(),
(HERE / "run_leo_clone_bound_handler_checkpoint.py").resolve(),
(HERE / "run_approve_claim_clone_canary.py").resolve(),
(HERE / "approve_proposal.py").resolve(),
(HERE / "apply_proposal.py").resolve(),
):
content = path.read_bytes()
records.append(
{
"repo_relative_path": path.relative_to(REPO_ROOT.resolve()).as_posix(),
"sha256": hashlib.sha256(content).hexdigest(),
"size_bytes": len(content),
}
)
return sorted(records, key=lambda row: row["repo_relative_path"])
async def run_lifecycle(args: argparse.Namespace) -> dict[str, Any]:
validate_args(args)
fixture = build_lifecycle_fixture(args.run_marker)
prompts = lifecycle_prompts(fixture, args.conversation_marker)
expected_rows = guarded._expected_bundle_rows(fixture["apply_payload"])
report: dict[str, Any] = {
"schema": SCHEMA,
"generated_at_utc": bound.utc_now(),
"current_canary": (
"one no-send GatewayRunner lifecycle against an existing disposable full-data Postgres clone"
),
"required_tier": "live_vps_no_send_disposable_full_data_clone",
"mode": "live_vps_gatewayrunner_clone_stage_review_apply_restart_recall_no_send",
"posted_to_telegram": False,
"production_writes_attempted": False,
"production_service_restart_attempted": False,
"clone_created_or_dropped": False,
"target": {"container": args.container, "database": args.db},
"markers": {
"run_marker": args.run_marker,
"conversation_marker": args.conversation_marker,
"conversation_marker_persisted_in_mutation_payload": False,
},
"fixture_ids": {
"proposal_id": fixture["proposal_id"],
"claim_id": fixture["claim_id"],
"source_id": fixture["source_id"],
"apply_payload_sha256": _json_hash(fixture["apply_payload"]),
"proposal_payload_sha256": _json_hash(fixture["proposal_payload"]),
},
"model_authority": {
"read_commands": sorted(READ_ONLY_COMMANDS),
"staging_commands": sorted(STAGING_COMMANDS),
"can_approve": False,
"can_apply": False,
"can_send": False,
},
"operator_authority": {
"review_requested": args.operator_review,
"guarded_apply_requested": args.guarded_apply,
"reviewer_handle": REVIEWER_HANDLE,
"applied_by_handle": APPLIED_BY_HANDLE,
"target_pinned_to_supplied_clone": True,
},
"source_manifest_before": _source_manifest(),
"expected_canonical_rows": expected_rows,
"turns": {},
"errors": [],
"output": str(args.output),
}
temp_profile: Path | None = None
tool_log: Path | None = None
provider_environment: dict[str, str] = {}
production_guard_before: dict[str, Any] | None = None
production_service_before: dict[str, Any] | None = None
live_bridge_before: dict[str, str | None] | None = None
target_guard_before: dict[str, Any] | None = None
target_base_guard_before: dict[str, Any] | None = None
target_unrelated_before: dict[str, Any] | None = None
target_container_id: str | None = None
target_identity_after: dict[str, Any] | None = None
bridge: dict[str, Any] = {}
provider_secret_values: tuple[str, ...] = ()
try:
target_identity, production_identity = assert_disposable_target(args.container, args.db)
target_container_id = str(target_identity["id"])
args.bound_container_id = target_container_id
report["target"].update(
{
"requested_container": args.container,
"bound_container_id": target_container_id,
"container_identity_before": target_identity,
"isolation_checks": bound.validate_disposable_target_identity(target_identity, production_identity),
}
)
report["production_invariants"] = {"container_identity": production_identity}
production_guard_before = bound.database_guard_snapshot(
bound.PRODUCTION_CONTAINER, bound.PRODUCTION_DB, tables=PRODUCTION_TABLES
)
production_service_before = bound.service_state()
live_bridge_before = bound.bridge_hashes()
target_base_guard_before = bound.database_guard_snapshot(
target_container_id, args.db, tables=PRODUCTION_TABLES
)
target_guard_before = bound.database_guard_snapshot(target_container_id, args.db, tables=LIFECYCLE_TABLES)
args.target_database_identity = target_guard_before["database_identity"]
if target_guard_before.get("database_identity", {}).get("system_identifier") == production_guard_before.get(
"database_identity", {}
).get("system_identifier"):
raise bound.CheckpointError("target and production resolve to the same Postgres system identifier")
report["production_invariants"].update(
{
"guard_snapshot_before": production_guard_before,
"service_before": production_service_before,
"live_bridge_hashes_before": live_bridge_before,
}
)
report["target_guard_snapshot_before"] = target_guard_before
report["target_base_guard_snapshot_before"] = target_base_guard_before
report["clone_baseline_matches_production"] = _snapshot_matches_production(
target_base_guard_before, production_guard_before
)
if not report["clone_baseline_matches_production"]:
raise bound.CheckpointError("target is not an exact full-data clone of production across base tables")
if guarded._proposal_readback(target_container_id, args.db, fixture["proposal_id"]) is not None:
raise bound.CheckpointError("run marker is not unique: deterministic proposal already exists")
if guarded._exact_bundle_readback(target_container_id, args.db, fixture["apply_payload"]) != {
key: [] for key in expected_rows
}:
raise bound.CheckpointError("run marker is not unique: deterministic canonical rows already exist")
target_unrelated_before = target_unrelated_guard_snapshot(target_container_id, args.db, fixture)
report["target_unrelated_guard_before"] = target_unrelated_before
missing_secrets = [
label
for label, path in (
("review", Path(args.review_secrets_file)),
("apply", Path(args.apply_secrets_file)),
)
if not path.is_file()
]
if missing_secrets:
raise bound.CheckpointError(
"required separated clone credential file(s) are absent: " + ", ".join(missing_secrets)
)
temp_profile, copy_audit = bound.copy_profile(
run_id=args.run_marker,
prompt_id="lifecycle",
)
report["temporary_profile_copy_audit"] = copy_audit
report["model_auth_binding"] = bound.copy_ephemeral_model_auth(temp_profile)
provider_environment, environment_audit = bound.load_ephemeral_provider_environment(temp_profile)
provider_secret_values = tuple(provider_environment.values())
report["model_auth_binding"]["environment_binding"] = environment_audit
bridge = patch_lifecycle_bridge(
temp_profile,
container=target_container_id,
database=args.db,
fixture=fixture,
)
report["temporary_bridge"] = bridge
tool_log = Path(bridge["tool_log_path"])
args.tool_run_nonce = bridge["run_nonce"]
with lifecycle_gateway_surface(allow_staging=False):
t1 = await run_gateway_turn(
args,
temp_profile,
phase="T1_conversation_marker",
prompt=prompts["T1_conversation_marker"],
provider_environment=provider_environment,
tool_log=tool_log,
)
_require_gateway_turn(t1)
report["turns"]["T1_conversation_marker"] = t1
target_guard_after_t1 = bound.database_guard_snapshot(target_container_id, args.db, tables=LIFECYCLE_TABLES)
report["target_guard_snapshot_after_t1"] = target_guard_after_t1
report["T1_proposal_readback"] = guarded._proposal_readback(
target_container_id, args.db, fixture["proposal_id"]
)
if target_guard_after_t1 != target_guard_before or report["T1_proposal_readback"] is not None:
raise bound.CheckpointError("T1 changed clone database state before staging was authorized")
t2 = await run_gateway_turn(
args,
temp_profile,
phase="T2_stage_pending_proposal",
prompt=prompts["T2_stage_pending_proposal"],
provider_environment=provider_environment,
tool_log=tool_log,
)
_require_gateway_turn(t2)
report["turns"]["T2_stage_pending_proposal"] = t2
if STAGE_COMMAND not in _phase_commands(t2):
raise bound.CheckpointError("T2 did not invoke the staging-only lifecycle verb")
pending = guarded._proposal_readback(target_container_id, args.db, fixture["proposal_id"])
report["pending_readback"] = pending
if not pending or not bound._state_semantics(pending, "pending_review")["all"]:
raise bound.CheckpointError("T2 did not leave the exact proposal pending and unapplied")
report["pending_canonical_rows"] = guarded._exact_bundle_readback(
target_container_id, args.db, fixture["apply_payload"]
)
report["staging_idempotency_replay"] = stage_lifecycle_proposal(target_container_id, args.db, fixture)
counts_after_stage = bound.database_counts(target_container_id, args.db, tables=LIFECYCLE_TABLES)
report["target_counts_after_stage"] = counts_after_stage
review_dry_run, review_apply = run_operator_review(args, fixture["proposal_id"])
approved = guarded._proposal_readback(target_container_id, args.db, fixture["proposal_id"])
approval_snapshot = guarded._approval_snapshot_readback(
target_container_id, args.db, fixture["proposal_id"]
)
approved_rows = guarded._exact_bundle_readback(target_container_id, args.db, fixture["apply_payload"])
report["operator_review"] = {
"controller": "explicit_harness_operator_phase",
"reviewed_by": REVIEWER_HANDLE,
"review_note": REVIEW_NOTE,
"dry_run": _command_receipt(review_dry_run),
"dry_run_uses_approve_strict_proposal": ("kb_stage.approve_strict_proposal" in review_dry_run.stdout),
"apply": _command_receipt(review_apply),
}
report["approved_unapplied_readback"] = approved
report["immutable_approval_readback"] = approval_snapshot
report["approved_canonical_rows"] = approved_rows
report["target_counts_after_approval"] = bound.database_counts(
target_container_id, args.db, tables=LIFECYCLE_TABLES
)
if not guarded._approval_transition_valid(pending, approved):
raise bound.CheckpointError("operator review did not produce the exact approved transition")
if approved_rows != {key: [] for key in expected_rows}:
raise bound.CheckpointError("canonical rows appeared before guarded apply")
t3 = await run_gateway_turn(
args,
temp_profile,
phase="T3_approved_unapplied_readback",
prompt=prompts["T3_approved_unapplied_readback"],
provider_environment=provider_environment,
tool_log=tool_log,
)
_require_gateway_turn(t3)
report["turns"]["T3_approved_unapplied_readback"] = t3
apply_dry_run, apply_execute = run_guarded_apply(args, fixture["proposal_id"])
report["guarded_apply"] = {
"controller": "explicit_harness_operator_phase",
"applied_by": APPLIED_BY_HANDLE,
"dry_run": _command_receipt(apply_dry_run),
"dry_run_uses_assert_approved_proposal": ("kb_stage.assert_approved_proposal" in apply_dry_run.stdout),
"dry_run_uses_finish_approved_proposal": ("kb_stage.finish_approved_proposal" in apply_dry_run.stdout),
"apply": _command_receipt(apply_execute),
}
applied = guarded._proposal_readback(target_container_id, args.db, fixture["proposal_id"])
approval_snapshot_after_apply = guarded._approval_snapshot_readback(
target_container_id, args.db, fixture["proposal_id"]
)
final_rows = guarded._exact_bundle_readback(target_container_id, args.db, fixture["apply_payload"])
final_counts = bound.database_counts(target_container_id, args.db, tables=LIFECYCLE_TABLES)
report["final_applied_readback"] = applied
report["immutable_approval_readback_after_apply"] = approval_snapshot_after_apply
report["final_canonical_rows"] = final_rows
report["target_counts_final"] = final_counts
report["target_deltas"] = {
"baseline_to_stage": _table_deltas(target_guard_before["counts"], counts_after_stage),
"stage_to_approval": _table_deltas(counts_after_stage, report["target_counts_after_approval"]),
"approved_to_applied": _table_deltas(report["target_counts_after_approval"], final_counts),
"baseline_to_final": _table_deltas(target_guard_before["counts"], final_counts),
}
if not guarded._apply_transition_valid(approved, applied):
raise bound.CheckpointError("guarded apply did not produce the exact applied transition")
if approval_snapshot_after_apply != approval_snapshot:
raise bound.CheckpointError("guarded apply changed the immutable approval snapshot")
if final_rows != expected_rows:
raise bound.CheckpointError("final canonical row projection does not match the reviewed payload")
t3_child = t3.get("gateway", {}).get("child_process") or {}
t5 = await run_gateway_turn(
args,
temp_profile,
phase="T5_recall_and_applied_readback",
prompt=prompts["T5_recall_and_applied_readback"],
provider_environment=provider_environment,
tool_log=tool_log,
)
_require_gateway_turn(t5)
report["turns"]["T5_recall_and_applied_readback"] = t5
t5_child = t5.get("gateway", {}).get("child_process") or {}
t3_gateway = t3.get("gateway") or {}
t5_gateway = t5.get("gateway") or {}
report["isolated_restart"] = {
"kind": "new GatewayRunner child process reopening the same private persisted session",
"service_restart_performed": False,
"prior_child_pid": t3_child.get("pid"),
"new_child_pid": t5_child.get("pid"),
"prior_child_absent_before_reopen": (
t3_child.get("alive_after_readback") is False
and t3_child.get("process_group_alive_after_readback") is False
),
"new_child_started": bool(t5_child.get("pid")),
"child_pid_changed": t3_child.get("pid") != t5_child.get("pid"),
"same_session_key": t3_gateway.get("session_key") == t5_gateway.get("session_key")
and bool(t3_gateway.get("session_key")),
"same_persisted_session_id": (
(t3_gateway.get("transcript_tool_trace") or {}).get("session_id")
== (t5_gateway.get("transcript_tool_trace") or {}).get("session_id")
and bool((t3_gateway.get("transcript_tool_trace") or {}).get("session_id"))
),
}
except Exception as exc:
report["errors"].append({"type": type(exc).__name__, "message": str(exc)})
report["traceback_tail"] = traceback.format_exc().splitlines()[-16:]
finally:
provider_environment.clear()
child_cleanup = bound.cleanup_active_gateway_children()
try:
if not tool_log or not target_container_id or not target_guard_before or not bridge.get("run_nonce"):
raise bound.CheckpointError("tool proof inputs were not established")
tool_proof = bound.read_tool_proof(
tool_log,
target_container_id,
args.db,
run_nonce=bridge["run_nonce"],
database_identity=target_guard_before["database_identity"],
require_database_read_only=False,
)
except Exception as exc:
tool_proof = {
"parse_errors": [str(exc)],
"event_count": 0,
"duplicate_invocation_ids": [],
"complete_start_end_pairing": False,
"invocations": [],
"invocation_count": 0,
"all_bound_to_supplied_target": False,
"database_read_only_required": False,
"all_completed_successfully": False,
}
report["errors"].append({"type": type(exc).__name__, "message": f"tool proof readback: {exc}"})
report["tool_proof"] = tool_proof
temp_root = temp_profile.parent if temp_profile else None
child_cleanup_clear = all(
item.get("alive_after_cleanup") is False and item.get("process_group_alive_after_cleanup") is False
for item in child_cleanup.values()
)
active_gateway_registry_clear = not bound._ACTIVE_GATEWAY_CHILDREN
temp_removed = bound.remove_tree(temp_root) if child_cleanup_clear and active_gateway_registry_clear else False
absence_verified = bound.temp_path_absent(temp_root)
report["cleanup"] = {
"active_gateway_child_cleanup": child_cleanup,
"temp_root": str(temp_root) if temp_root else None,
"temp_profile_removed": temp_removed,
"temp_session_removed_with_profile": temp_removed,
"absence_verified_independently": absence_verified,
"active_temp_root_registry_clear": (temp_root not in bound._ACTIVE_TEMP_ROOTS if temp_root else True),
"active_gateway_registry_clear": active_gateway_registry_clear,
"termination_signal": bound._LAST_TERMINATION_SIGNAL,
}
if target_container_id:
try:
target_identity_after = bound.container_identity(args.container)
if target_identity_after.get("id") != target_container_id:
raise bound.CheckpointError("target name no longer resolves to the pinned container identity")
production_identity = report.get("production_invariants", {}).get("container_identity") or {}
bound.validate_disposable_target_identity(target_identity_after, production_identity)
report["target"]["container_identity_after"] = target_identity_after
except Exception as exc:
report["errors"].append({"type": type(exc).__name__, "message": f"target identity postflight: {exc}"})
try:
target_guard_after = bound.database_guard_snapshot(
target_container_id, args.db, tables=LIFECYCLE_TABLES
)
report["target_guard_snapshot_after"] = target_guard_after
except Exception as exc:
report["errors"].append({"type": type(exc).__name__, "message": f"target postflight: {exc}"})
try:
target_unrelated_after = target_unrelated_guard_snapshot(target_container_id, args.db, fixture)
report["target_unrelated_guard_after"] = target_unrelated_after
report["target_unrelated_rows_unchanged"] = (
target_unrelated_before is not None and target_unrelated_before == target_unrelated_after
)
except Exception as exc:
report["target_unrelated_rows_unchanged"] = False
report["errors"].append(
{"type": type(exc).__name__, "message": f"target unrelated-row postflight: {exc}"}
)
else:
report["target_unrelated_rows_unchanged"] = False
try:
production_guard_after = bound.database_guard_snapshot(
bound.PRODUCTION_CONTAINER, bound.PRODUCTION_DB, tables=PRODUCTION_TABLES
)
except Exception as exc:
production_guard_after = None
report["errors"].append({"type": type(exc).__name__, "message": f"production postflight: {exc}"})
production_service_after = bound.service_state()
live_bridge_after = bound.bridge_hashes()
production = report.setdefault("production_invariants", {})
production.update(
{
"guard_snapshot_before": production_guard_before,
"guard_snapshot_after": production_guard_after,
"guard_snapshot_unchanged": production_guard_before is not None
and production_guard_before == production_guard_after,
"service_before": production_service_before,
"service_after": production_service_after,
"service_unchanged": _service_unchanged(production_service_before, production_service_after),
"live_bridge_hashes_before": live_bridge_before,
"live_bridge_hashes_after": live_bridge_after,
"live_bridge_unchanged": live_bridge_before is not None and live_bridge_before == live_bridge_after,
}
)
try:
report["source_manifest_after"] = _source_manifest()
report["source_files_unchanged_during_run"] = (
report["source_manifest_before"] == report["source_manifest_after"]
)
except Exception as exc:
report["errors"].append({"type": type(exc).__name__, "message": f"source manifest postflight: {exc}"})
report["checks"] = evaluate_checks(report, args, fixture)
report["status"] = "pass" if not report["errors"] and all(report["checks"].values()) else "fail"
report["current_tier"] = (
"live_vps_no_send_disposable_full_data_clone" if report["status"] == "pass" else "partial_or_failed"
)
report["claim_ceiling"] = (
"A passing receipt proves the real VPS GatewayRunner staged one deterministic pending proposal, "
"the harness alone reviewed and guarded-applied it in the supplied disposable full-data clone, "
"a reopened isolated handler recalled a conversation-only marker and read applied canonical rows, "
"and production fingerprints/service/bridge plus no-send cleanup invariants stayed unchanged. "
"It does not prove Telegram delivery or production mutation."
)
report["completed_at_utc"] = bound.utc_now()
report = bound.redact_value(report, secret_values=provider_secret_values)
bound.write_report(args.output, report, secret_values=provider_secret_values)
return report
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--container", required=True, help="Existing disposable Postgres container name.")
parser.add_argument("--db", required=True, help="Full-data database inside the disposable container.")
parser.add_argument("--output", required=True, type=Path, help="Private JSON receipt path.")
parser.add_argument("--run-marker", default=None)
parser.add_argument("--conversation-marker", default=None)
parser.add_argument("--chat-id", default=bound.DEFAULT_CHAT_ID)
parser.add_argument("--user-id", default=bound.DEFAULT_USER_ID)
parser.add_argument("--user-name", default="codex clone lifecycle checkpoint")
parser.add_argument("--turn-timeout", type=int, default=300)
parser.add_argument("--review-secrets-file", default=DEFAULT_REVIEW_SECRETS_FILE)
parser.add_argument("--apply-secrets-file", default=DEFAULT_APPLY_SECRETS_FILE)
parser.add_argument(
"--copy-model-auth",
action="store_true",
help="Copy only auth.json into the private temporary profile, then remove it.",
)
parser.add_argument(
"--operator-review",
action="store_true",
help="Explicitly allow the harness-owned kb_review phase in the supplied clone.",
)
parser.add_argument(
"--guarded-apply",
action="store_true",
help="Explicitly allow the harness-owned kb_apply phase in the supplied clone.",
)
args = parser.parse_args(argv)
args.run_marker = args.run_marker or new_marker("leo-lifecycle")
args.conversation_marker = args.conversation_marker or new_marker("conversation-memory")
return args
def parse_internal_stage_args(argv: list[str]) -> argparse.Namespace:
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("--container", required=True)
parser.add_argument("--db", required=True)
parser.add_argument("--run-marker", required=True)
return parser.parse_args(argv)
def internal_stage_main(argv: list[str]) -> int:
args = parse_internal_stage_args(argv)
try:
_validate_marker(args.run_marker, "--run-marker")
fixture = build_lifecycle_fixture(args.run_marker)
result = stage_lifecycle_proposal(args.container, args.db, fixture)
except Exception as exc:
print(json.dumps({"status": "rejected", "error": bound.redact_text(str(exc))}, sort_keys=True))
return 2
print(json.dumps({"status": "pending_review", **result}, sort_keys=True))
return 0
def main(argv: list[str] | None = None) -> int:
raw_argv = list(sys.argv[1:] if argv is None else argv)
if raw_argv and raw_argv[0] == INTERNAL_STAGE_COMMAND:
return internal_stage_main(raw_argv[1:])
args = parse_args(raw_argv)
try:
with bound.termination_cleanup_handlers():
report = asyncio.run(run_lifecycle(args))
except bound.CheckpointError as exc:
print(json.dumps({"status": "rejected", "error": str(exc)}, sort_keys=True))
return 2
except bound.TerminationRequested as exc:
print(
json.dumps(
{"status": "terminated", "signal": exc.signum, "output": str(args.output)},
sort_keys=True,
)
)
return 128 + exc.signum
print(
json.dumps(
{
"status": report.get("status"),
"output": str(args.output),
"checks_passed": sum(bool(value) for value in report.get("checks", {}).values()),
"checks_total": len(report.get("checks", {})),
"error_count": len(report.get("errors", [])),
},
sort_keys=True,
)
)
return 0 if report["status"] == "pass" else 1
if __name__ == "__main__":
raise SystemExit(main())