docs: capture personal-agent runtime readiness snapshot
This commit is contained in:
@@ -22,6 +22,7 @@ REQUIRED = [
|
||||
"docs/contracts/personal-agent-proton-rclone-package.json",
|
||||
"docs/contracts/personal-agent-secondbrain-proposal-route.json",
|
||||
"docs/contracts/personal-agent-conductor-curator-service-handoff.json",
|
||||
"docs/contracts/personal-agent-runtime-readiness-snapshot.json",
|
||||
"docs/prd/2026-06-14-personal-agent-context-runtime-prd.md",
|
||||
"docs/issues/2026-06-14-personal-agent-context-runtime-work-orders.md",
|
||||
"docs/supersession/2026-06-14-personal-agent-context-runtime-supersession-register.md",
|
||||
@@ -112,6 +113,23 @@ REQUIRED_HANDOFF_SERVICES = {
|
||||
"personal-agent.secondbrain.proposal-route",
|
||||
}
|
||||
|
||||
REQUIRED_RUNTIME_SURFACES = {
|
||||
"imessage.read",
|
||||
"mail.read",
|
||||
"calendar.read",
|
||||
"contacts.read",
|
||||
"drive.read",
|
||||
}
|
||||
|
||||
REQUIRED_RUNTIME_GAPS = {
|
||||
"proton-email-gate-exited",
|
||||
"proton-contacts-gate-exited",
|
||||
"stale-protonmail-bridge-container",
|
||||
"proton-rclone-child-unregistered",
|
||||
"secondbrain-apply-blocked",
|
||||
"desktop-adapter-exposure-blocked",
|
||||
}
|
||||
|
||||
|
||||
def read_text(rel: str) -> str:
|
||||
return (ROOT / rel).read_text(encoding="utf-8")
|
||||
@@ -148,6 +166,7 @@ def main() -> int:
|
||||
"PACR-004",
|
||||
"PACR-005",
|
||||
"PACR-006",
|
||||
"PACR-007",
|
||||
"status: candidate",
|
||||
"owner: jp",
|
||||
]:
|
||||
@@ -739,6 +758,121 @@ def main() -> int:
|
||||
if remaining_gates.get(gate) != "blocked-follow-up":
|
||||
errors.append(f"service_handoff_remaining_gate_missing:{gate}")
|
||||
|
||||
runtime = load_json("docs/contracts/personal-agent-runtime-readiness-snapshot.json", errors)
|
||||
if runtime:
|
||||
if runtime.get("schema_version") != "personal-agent-runtime-readiness-snapshot/v1":
|
||||
errors.append("runtime_snapshot_schema_version_invalid")
|
||||
if runtime.get("status") != "active-redacted-runtime-snapshot":
|
||||
errors.append("runtime_snapshot_status_invalid")
|
||||
if runtime.get("profile_identity") != "personal-agent":
|
||||
errors.append("runtime_snapshot_profile_identity_not_personal_agent")
|
||||
if runtime.get("display_name") != "Steev":
|
||||
errors.append("runtime_snapshot_display_name_not_steev")
|
||||
if runtime.get("aggregate_runtime_state") != "degraded":
|
||||
errors.append("runtime_snapshot_aggregate_not_degraded")
|
||||
for key in ["runtime_readiness_claimed", "seed_readiness_claimed", "core_promotion_claimed"]:
|
||||
if runtime.get(key) is not False:
|
||||
errors.append(f"runtime_snapshot_overclaim:{key}")
|
||||
if runtime.get("memory_target") != "secondbrain-personal":
|
||||
errors.append("runtime_snapshot_memory_target_not_secondbrain_personal")
|
||||
if "orgbrain" not in runtime.get("forbidden_memory_targets", []):
|
||||
errors.append("runtime_snapshot_orgbrain_not_forbidden")
|
||||
surfaces = runtime.get("surface_states", [])
|
||||
surface_names = {surface.get("surface") for surface in surfaces}
|
||||
missing_surfaces = sorted(REQUIRED_RUNTIME_SURFACES - surface_names)
|
||||
if missing_surfaces:
|
||||
errors.append(f"runtime_snapshot_surfaces_missing:{','.join(missing_surfaces)}")
|
||||
state_by_surface = {surface.get("surface"): surface.get("readiness_state") for surface in surfaces}
|
||||
if state_by_surface.get("imessage.read") != "ready":
|
||||
errors.append("runtime_snapshot_imessage_not_ready")
|
||||
for surface in ["mail.read", "calendar.read", "contacts.read", "drive.read"]:
|
||||
if state_by_surface.get(surface) != "degraded":
|
||||
errors.append(f"runtime_snapshot_surface_not_degraded:{surface}")
|
||||
for surface in surfaces:
|
||||
name = surface.get("surface", "<unknown>")
|
||||
if surface.get("readiness_state") not in {"ready", "degraded", "pending", "blocked", "disabled"}:
|
||||
errors.append(f"runtime_snapshot_readiness_invalid:{name}")
|
||||
if not surface.get("capability_package"):
|
||||
errors.append(f"runtime_snapshot_package_missing:{name}")
|
||||
if not surface.get("health_source"):
|
||||
errors.append(f"runtime_snapshot_health_source_missing:{name}")
|
||||
health = surface.get("redacted_health")
|
||||
if not isinstance(health, dict):
|
||||
errors.append(f"runtime_snapshot_health_not_object:{name}")
|
||||
if "raw_mail_observed" in health and health.get("raw_mail_observed") is not False:
|
||||
errors.append("runtime_snapshot_raw_mail_observed")
|
||||
if "raw_calendar_events_observed" in health and health.get("raw_calendar_events_observed") is not False:
|
||||
errors.append("runtime_snapshot_raw_calendar_observed")
|
||||
if "raw_contacts_observed" in health and health.get("raw_contacts_observed") is not False:
|
||||
errors.append("runtime_snapshot_raw_contacts_observed")
|
||||
if "drive_file_names_observed" in health and health.get("drive_file_names_observed") is not False:
|
||||
errors.append("runtime_snapshot_drive_file_names_observed")
|
||||
if "drive_file_contents_observed" in health and health.get("drive_file_contents_observed") is not False:
|
||||
errors.append("runtime_snapshot_drive_file_contents_observed")
|
||||
imessage_health = next((surface.get("redacted_health", {}) for surface in surfaces if surface.get("surface") == "imessage.read"), {})
|
||||
if imessage_health.get("validator_ok") is not True:
|
||||
errors.append("runtime_snapshot_bluebubbles_validator_not_ok")
|
||||
if imessage_health.get("read_only_imessage") is not True:
|
||||
errors.append("runtime_snapshot_imessage_not_readonly")
|
||||
if imessage_health.get("package_runtime_claims") is not False:
|
||||
errors.append("runtime_snapshot_bluebubbles_runtime_claim_overclaimed")
|
||||
posture = runtime.get("supervisor_posture", {})
|
||||
expected_posture = {
|
||||
"mac_mini_bluebubbles": "package-validator-ok-redacted",
|
||||
"proton_bridge_service": "active-running",
|
||||
"proton_bridge_proxy_service": "active-running",
|
||||
"rclone_rc_service": "disabled-inactive",
|
||||
"rclone_proxy_service": "disabled-inactive",
|
||||
}
|
||||
for key, expected in expected_posture.items():
|
||||
if posture.get(key) != expected:
|
||||
errors.append(f"runtime_snapshot_posture_mismatch:{key}")
|
||||
gaps = {gap.get("id") for gap in runtime.get("named_runtime_gaps", [])}
|
||||
missing_gaps = sorted(REQUIRED_RUNTIME_GAPS - gaps)
|
||||
if missing_gaps:
|
||||
errors.append(f"runtime_snapshot_gaps_missing:{','.join(missing_gaps)}")
|
||||
reboot = runtime.get("optional_reboot_power_loss_proof", {})
|
||||
if reboot.get("status") != "not-run":
|
||||
errors.append("runtime_snapshot_reboot_status_not_not_run")
|
||||
if reboot.get("required_for_final_always_on_claim") is not True:
|
||||
errors.append("runtime_snapshot_reboot_not_required_for_final")
|
||||
commands = set(runtime.get("observed_commands", []))
|
||||
for command in [
|
||||
"python3 tools/validate_bluebubbles_child.py",
|
||||
"hermes -p steev mcp list",
|
||||
"rclone --config /home/svrnty/.config/rclone/rclone.conf about proton: --json",
|
||||
]:
|
||||
if command not in commands:
|
||||
errors.append(f"runtime_snapshot_observed_command_missing:{command}")
|
||||
forbidden_fields = set(runtime.get("proof_policy", {}).get("forbidden_fields", []))
|
||||
for field in [
|
||||
"raw_messages",
|
||||
"message_text",
|
||||
"mail_bodies",
|
||||
"contact_details",
|
||||
"calendar_event_details",
|
||||
"drive_file_names",
|
||||
"drive_file_contents",
|
||||
"endpoint_payloads",
|
||||
"credentials",
|
||||
"secret_values",
|
||||
]:
|
||||
if field not in forbidden_fields:
|
||||
errors.append(f"runtime_snapshot_forbidden_field_missing:{field}")
|
||||
remaining_gates = runtime.get("remaining_gates", {})
|
||||
for gate in [
|
||||
"proton_email_gate_repair",
|
||||
"proton_contacts_gate_repair",
|
||||
"proton_rclone_child_registration",
|
||||
"secondbrain_durable_apply",
|
||||
"desktop_adapter_exposure",
|
||||
"final_acceptance_packet",
|
||||
]:
|
||||
if remaining_gates.get(gate) != "blocked-follow-up":
|
||||
errors.append(f"runtime_snapshot_remaining_gate_missing:{gate}")
|
||||
if remaining_gates.get("reboot_power_loss_drill") != "optional-follow-up":
|
||||
errors.append("runtime_snapshot_reboot_gate_missing")
|
||||
|
||||
for rel in ["AGENT.md", "CONTRACT.md", "DISCLOSURE.md", "README.md", "docs/STEEV-MASTER.md"]:
|
||||
path = ROOT / rel
|
||||
if not path.exists():
|
||||
@@ -760,6 +894,7 @@ def main() -> int:
|
||||
"Proton/rclone package candidate",
|
||||
"Personal-agent Secondbrain proposal route",
|
||||
"Personal-agent Conductor/Curator service handoff",
|
||||
"Personal-agent runtime readiness snapshot",
|
||||
"superseded",
|
||||
"legacy-reference",
|
||||
"blocked-follow-up",
|
||||
@@ -775,7 +910,7 @@ def main() -> int:
|
||||
|
||||
result = {
|
||||
"ok": not errors,
|
||||
"validator": "personal-agent-profile-distribution-v5",
|
||||
"validator": "personal-agent-profile-distribution-v6",
|
||||
"checked": REQUIRED,
|
||||
"errors": errors,
|
||||
"warnings": [],
|
||||
|
||||
Reference in New Issue
Block a user