diff --git a/WORKBOARD.yaml b/WORKBOARD.yaml index c0fe07c..716668a 100644 --- a/WORKBOARD.yaml +++ b/WORKBOARD.yaml @@ -64,3 +64,8 @@ items: status: complete source: docs/contracts/personal-agent-proton-rclone-package.json owner: jp + - id: PACR-012 + title: Proton/rclone Runtime Gate Repair Pickup + status: complete + source: docs/contracts/personal-agent-proton-rclone-package.json + owner: jp diff --git a/docs/contracts/personal-agent-proton-rclone-package.json b/docs/contracts/personal-agent-proton-rclone-package.json index 9cd8157..20e9fef 100644 --- a/docs/contracts/personal-agent-proton-rclone-package.json +++ b/docs/contracts/personal-agent-proton-rclone-package.json @@ -13,13 +13,21 @@ "core_promotion_claimed": false, "child_workspace_candidate": { "path": "../proton-rclone", - "commit": "c49f85691232c317d694725445ec3acbf127c72b", + "commit": "c740d1ee6acfdb1d62b56cb38f2121a26e07ae1e", "validator_command": "python3 tools/validate_proton_rclone_child.py", "validator_result_observed": "ok", "core_registration_claimed": false, "runtime_readiness_claimed": false, "core_registration_candidate_packet": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-core-registration-candidate-packet.json", - "live_redacted_health_proof": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-live-redacted-health.json" + "live_redacted_health_proof": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-live-redacted-health.json", + "runtime_gate_repair_proof": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-runtime-gate-repair-proof.json", + "current_runtime_state_reconciliation": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-current-runtime-state-reconciliation.json", + "source_hashes": { + "readonly_contract": "47bcbdf69152c709c728cca725a88c92de418280705357a57ea658ca9b24d607", + "live_redacted_health": "26ce58fe5ca74a66342dd3b28e223227eac74f6b91ee18a7cdd6acfae720579c", + "runtime_gate_repair_proof": "b200fa1f446165185821f6c3b51825b517b00777d502d30ce90665cfee1cd6a1", + "current_runtime_state_reconciliation": "0bfeb8f5d0977f43ffd04c468d445cf22fbeca8578d59fb38e014094a5e4cd07" + } }, "authority_boundary": { "profile_owns_surface_exposure": true, @@ -208,7 +216,7 @@ "overall_state": "degraded", "chosen_runtime_path": "MCP facades for Mail, Calendar, Contacts; explicit rclone config for Drive", "pending_runtime_convergence": [ - "Repair or replace not-up email and contacts gate containers.", + "Promote the repaired email and contacts gate bind-mount shape into a canonical runtime deployment route.", "Resolve auto-restarting user proton-bridge and proton-bridge-proxy units or explicitly abandon them.", "Keep rclone RC/proxy units disabled unless a governed wrapper admits them.", "Promote/register proton-rclone through Core before package runtime readiness is claimed." @@ -238,11 +246,11 @@ }, { "name": "sdo-email-gate", - "observed_state": "not-up" + "observed_state": "up" }, { "name": "sdo-contacts-gate", - "observed_state": "not-up" + "observed_state": "up" }, { "name": "stale-sdo-protonmail-bridge-container", @@ -358,10 +366,10 @@ "remaining_gates": { "child_workspace_candidate": "complete-child-local", "registered_child_workspace": "blocked-follow-up", - "email_gate_repair": "blocked-follow-up", - "contacts_gate_repair": "blocked-follow-up", + "email_gate_repair": "complete-child-local", + "contacts_gate_repair": "complete-child-local", "systemd_bridge_convergence": "blocked-follow-up", "secondbrain_durable_apply": "blocked-follow-up", - "seed_package_pickup": "blocked-follow-up" + "seed_package_pickup": "blocked-after-runtime-repair-source-lock-refresh" } } diff --git a/docs/contracts/personal-agent-runtime-readiness-snapshot.json b/docs/contracts/personal-agent-runtime-readiness-snapshot.json index 75b5cd5..c8826b1 100644 --- a/docs/contracts/personal-agent-runtime-readiness-snapshot.json +++ b/docs/contracts/personal-agent-runtime-readiness-snapshot.json @@ -39,12 +39,12 @@ "mcp_server_enabled": true, "proton_bridge_systemd_running": false, "proton_bridge_systemd_state": "activating-auto-restart", - "docker_email_gate": "not-up", + "docker_email_gate": "up", "child_workspace_candidate_validator_ok": true, "core_child_workspace_registered": false, "raw_mail_observed": false }, - "remaining_gap": "Email gate repair or replacement and Core child registration remain required." + "remaining_gap": "Email gate is repaired child-local; Proton Bridge systemd convergence and Core child registration remain required." }, { "surface": "calendar.read", @@ -69,12 +69,12 @@ "health_source": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-live-redacted-health.json", "redacted_health": { "mcp_server_enabled": true, - "docker_contacts_gate": "not-up", + "docker_contacts_gate": "up", "child_workspace_candidate_validator_ok": true, "core_child_workspace_registered": false, "raw_contacts_observed": false }, - "remaining_gap": "Contacts gate repair or replacement and Core child registration remain required." + "remaining_gap": "Contacts gate is repaired child-local; Core child registration and final runtime acceptance remain required." }, { "surface": "drive.read", @@ -103,16 +103,16 @@ }, "named_runtime_gaps": [ { - "id": "proton-email-gate-exited", - "severity": "must-fix", - "state": "email gate not-up", - "impact": "mail.read remains degraded" + "id": "proton-runtime-gate-repair-source-lock-refresh", + "severity": "follow-up", + "state": "email and contacts gates repaired child-local; Seed and downstream profile snapshots need pickup", + "impact": "runtime remains degraded until source locks and final acceptance catch up" }, { - "id": "proton-contacts-gate-exited", + "id": "proton-rclone-service-posture-disabled", "severity": "must-fix", - "state": "contacts gate not-up", - "impact": "contacts.read remains degraded" + "state": "rclone-rc.service and rclone-proxy.service are disabled and inactive", + "impact": "Drive read can use redacted CLI proof, but an always-on runtime API is not claimed" }, { "id": "stale-protonmail-bridge-container", @@ -177,8 +177,8 @@ ] }, "remaining_gates": { - "proton_email_gate_repair": "blocked-follow-up", - "proton_contacts_gate_repair": "blocked-follow-up", + "proton_email_gate_repair": "complete-child-local", + "proton_contacts_gate_repair": "complete-child-local", "proton_bridge_systemd_convergence": "blocked-follow-up", "proton_rclone_child_candidate": "complete-child-local", "proton_rclone_child_registration": "blocked-follow-up", diff --git a/docs/evidence/2026-06-14-personal-agent-proton-rclone-runtime-reconciliation.md b/docs/evidence/2026-06-14-personal-agent-proton-rclone-runtime-reconciliation.md index 74d9214..1fa3346 100644 --- a/docs/evidence/2026-06-14-personal-agent-proton-rclone-runtime-reconciliation.md +++ b/docs/evidence/2026-06-14-personal-agent-proton-rclone-runtime-reconciliation.md @@ -19,9 +19,9 @@ against a same-day redacted runtime probe. - MCP registration: `proton-calendar`, `proton-email`, and `proton-contacts` are enabled for the Steev profile. -- Docker inventory: calendar gate is up, email gate and contacts gate remain - exited, one Proton Bridge container is up, and one stale Proton Bridge - container remains created. +- Docker inventory: calendar, email, and contacts gates are up after the + child-local bind-mount repair; one Proton Bridge container is up, and one + stale Proton Bridge container remains created. - systemd user inventory: `proton-bridge.service` and `proton-bridge-proxy.service` are loaded and enabled but currently `activating-auto-restart`. @@ -30,8 +30,10 @@ against a same-day redacted runtime probe. ## Result -The profile runtime snapshot now records Proton Bridge systemd convergence as a -must-fix gap. The aggregate `personal-agent` runtime state remains degraded. +The profile runtime snapshot now records the email and contacts gate repair as +complete child-local. The aggregate `personal-agent` runtime state remains +degraded because Core registration, Proton Bridge systemd convergence, rclone +service posture, source-lock pickup, and final acceptance remain open. This proof does not read or store mail bodies, mail subjects, sender or recipient addresses, contact details, calendar event details, drive file names, diff --git a/docs/supersession/2026-06-14-personal-agent-context-runtime-supersession-register.md b/docs/supersession/2026-06-14-personal-agent-context-runtime-supersession-register.md index b4f16bf..bf81e37 100644 --- a/docs/supersession/2026-06-14-personal-agent-context-runtime-supersession-register.md +++ b/docs/supersession/2026-06-14-personal-agent-context-runtime-supersession-register.md @@ -34,7 +34,7 @@ desktop exposure must be treated as one of: | Personal-agent BlueBubbles binding | active-authority | `docs/contracts/personal-agent-bluebubbles-binding.json` binds `imessage.read` to the package | | BlueBubbles iMessage | active-capability-package | BlueBubbles child completion-readiness package | | Proton/rclone package candidate | active-authority | `docs/contracts/personal-agent-proton-rclone-package.json` links to the child-local `../proton-rclone` candidate without Core registration or runtime readiness overclaim | -| Proton Mail/Calendar/Contacts | blocked-follow-up | Child candidate exists; Core registration, degraded gate repair, and final readiness remain follow-up work | +| Proton Mail/Calendar/Contacts | blocked-follow-up | Child candidate exists and email/contacts gates are repaired child-local; Core registration, bridge convergence, source-lock pickup, and final readiness remain follow-up work | | Proton Drive/rclone | blocked-follow-up | Child candidate has redacted rclone `about` proof; governed wrapper and write gates remain follow-up work | | Personal-agent Secondbrain proposal/apply route | active-authority | `docs/contracts/personal-agent-secondbrain-proposal-route.json` defines proposal-only personal memory intake and references the governed Secondbrain apply route | | Personal memory live durable apply | blocked-follow-up | Secondbrain apply route is defined, but live apply still requires approval; profile/capability packages do not write durable memory | diff --git a/tools/validate_steev_child.py b/tools/validate_steev_child.py index 9af4b4b..1c8b44e 100755 --- a/tools/validate_steev_child.py +++ b/tools/validate_steev_child.py @@ -124,8 +124,8 @@ REQUIRED_RUNTIME_SURFACES = { } REQUIRED_RUNTIME_GAPS = { - "proton-email-gate-exited", - "proton-contacts-gate-exited", + "proton-runtime-gate-repair-source-lock-refresh", + "proton-rclone-service-posture-disabled", "stale-protonmail-bridge-container", "proton-bridge-systemd-auto-restart", "proton-rclone-child-unregistered", @@ -201,6 +201,7 @@ def main() -> int: "PACR-008", "PACR-010", "PACR-011", + "PACR-012", "status: candidate", "owner: jp", ]: @@ -364,15 +365,27 @@ def main() -> int: candidate = proton.get("child_workspace_candidate", {}) expected_candidate = { "path": "../proton-rclone", - "commit": "c49f85691232c317d694725445ec3acbf127c72b", + "commit": "c740d1ee6acfdb1d62b56cb38f2121a26e07ae1e", "validator_command": "python3 tools/validate_proton_rclone_child.py", "validator_result_observed": "ok", "core_registration_candidate_packet": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-core-registration-candidate-packet.json", "live_redacted_health_proof": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-live-redacted-health.json", + "runtime_gate_repair_proof": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-runtime-gate-repair-proof.json", + "current_runtime_state_reconciliation": "../proton-rclone/.sot/08-OUTPUTS/proton-rclone-current-runtime-state-reconciliation.json", } for key, expected in expected_candidate.items(): if candidate.get(key) != expected: errors.append(f"proton_rclone_child_candidate_mismatch:{key}") + expected_hashes = { + "readonly_contract": "47bcbdf69152c709c728cca725a88c92de418280705357a57ea658ca9b24d607", + "live_redacted_health": "26ce58fe5ca74a66342dd3b28e223227eac74f6b91ee18a7cdd6acfae720579c", + "runtime_gate_repair_proof": "b200fa1f446165185821f6c3b51825b517b00777d502d30ce90665cfee1cd6a1", + "current_runtime_state_reconciliation": "0bfeb8f5d0977f43ffd04c468d445cf22fbeca8578d59fb38e014094a5e4cd07", + } + hashes = candidate.get("source_hashes", {}) + for key, expected in expected_hashes.items(): + if hashes.get(key) != expected: + errors.append(f"proton_rclone_child_hash_mismatch:{key}") for key in ["core_registration_claimed", "runtime_readiness_claimed"]: if candidate.get(key) is not False: errors.append(f"proton_rclone_child_candidate_overclaim:{key}") @@ -449,10 +462,10 @@ def main() -> int: for name in ["sdo-calendar-gate", "sdo-email-gate", "sdo-contacts-gate"]: if name not in docker: errors.append(f"proton_rclone_docker_route_missing:{name}") - if docker.get("sdo-email-gate") != "not-up": - errors.append("proton_rclone_email_gate_state_not_captured") - if docker.get("sdo-contacts-gate") != "not-up": - errors.append("proton_rclone_contacts_gate_state_not_captured") + if docker.get("sdo-email-gate") != "up": + errors.append("proton_rclone_email_gate_state_not_up") + if docker.get("sdo-contacts-gate") != "up": + errors.append("proton_rclone_contacts_gate_state_not_up") units = {item.get("name"): item for item in inventory.get("systemd_user_units", [])} if units.get("proton-bridge.service", {}).get("observed_state") != "activating-auto-restart": errors.append("proton_rclone_proton_bridge_gap_not_captured") @@ -508,16 +521,19 @@ def main() -> int: remaining_gates = proton.get("remaining_gates", {}) if remaining_gates.get("child_workspace_candidate") != "complete-child-local": errors.append("proton_rclone_child_candidate_gate_missing") + if remaining_gates.get("email_gate_repair") != "complete-child-local": + errors.append("proton_rclone_email_gate_repair_not_complete") + if remaining_gates.get("contacts_gate_repair") != "complete-child-local": + errors.append("proton_rclone_contacts_gate_repair_not_complete") for gate in [ "registered_child_workspace", - "email_gate_repair", - "contacts_gate_repair", "systemd_bridge_convergence", "secondbrain_durable_apply", - "seed_package_pickup", ]: if remaining_gates.get(gate) != "blocked-follow-up": errors.append(f"proton_rclone_remaining_gate_missing:{gate}") + if remaining_gates.get("seed_package_pickup") != "blocked-after-runtime-repair-source-lock-refresh": + errors.append("proton_rclone_seed_pickup_gate_invalid") memory_route = load_json("docs/contracts/personal-agent-secondbrain-proposal-route.json", errors) if memory_route: @@ -962,9 +978,11 @@ def main() -> int: errors.append("runtime_snapshot_governed_apply_route_not_defined") if remaining_gates.get("proton_rclone_child_candidate") != "complete-child-local": errors.append("runtime_snapshot_child_candidate_gate_missing") + if remaining_gates.get("proton_email_gate_repair") != "complete-child-local": + errors.append("runtime_snapshot_email_gate_repair_not_complete") + if remaining_gates.get("proton_contacts_gate_repair") != "complete-child-local": + errors.append("runtime_snapshot_contacts_gate_repair_not_complete") for gate in [ - "proton_email_gate_repair", - "proton_contacts_gate_repair", "proton_rclone_child_registration", "secondbrain_durable_apply", "desktop_adapter_exposure",