docs: define personal-agent desktop exposure contract
This commit is contained in:
@@ -11,6 +11,7 @@ JP's personal assistant / chief of staff. Daily briefing, inbox triage, comms in
|
|||||||
- **Secondbrain proposal route:** [`docs/contracts/personal-agent-secondbrain-proposal-route.json`](docs/contracts/personal-agent-secondbrain-proposal-route.json) — proposal-only personal memory intake; durable apply remains owned by Secondbrain.
|
- **Secondbrain proposal route:** [`docs/contracts/personal-agent-secondbrain-proposal-route.json`](docs/contracts/personal-agent-secondbrain-proposal-route.json) — proposal-only personal memory intake; durable apply remains owned by Secondbrain.
|
||||||
- **Conductor/Curator service handoff:** [`docs/contracts/personal-agent-conductor-curator-service-handoff.json`](docs/contracts/personal-agent-conductor-curator-service-handoff.json) — redacted service map for future route selection and hygiene review pickup.
|
- **Conductor/Curator service handoff:** [`docs/contracts/personal-agent-conductor-curator-service-handoff.json`](docs/contracts/personal-agent-conductor-curator-service-handoff.json) — redacted service map for future route selection and hygiene review pickup.
|
||||||
- **Runtime readiness snapshot:** [`docs/contracts/personal-agent-runtime-readiness-snapshot.json`](docs/contracts/personal-agent-runtime-readiness-snapshot.json) — redacted per-surface runtime state and gaps; aggregate readiness remains degraded.
|
- **Runtime readiness snapshot:** [`docs/contracts/personal-agent-runtime-readiness-snapshot.json`](docs/contracts/personal-agent-runtime-readiness-snapshot.json) — redacted per-surface runtime state and gaps; aggregate readiness remains degraded.
|
||||||
|
- **Desktop exposure contract:** [`docs/contracts/personal-agent-desktop-exposure-contract.json`](docs/contracts/personal-agent-desktop-exposure-contract.json) — adapter-facing state rows for Desktop/Dashboard display; no UI wiring from this route.
|
||||||
- **Historical Steev reference redirect:** [`docs/STEEV-MASTER.md`](docs/STEEV-MASTER.md).
|
- **Historical Steev reference redirect:** [`docs/STEEV-MASTER.md`](docs/STEEV-MASTER.md).
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
|||||||
@@ -44,3 +44,8 @@ items:
|
|||||||
status: complete
|
status: complete
|
||||||
source: docs/contracts/personal-agent-runtime-readiness-snapshot.json
|
source: docs/contracts/personal-agent-runtime-readiness-snapshot.json
|
||||||
owner: jp
|
owner: jp
|
||||||
|
- id: PACR-008
|
||||||
|
title: Desktop Adapter Exposure Contract
|
||||||
|
status: complete
|
||||||
|
source: docs/contracts/personal-agent-desktop-exposure-contract.json
|
||||||
|
owner: jp
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ Active authority:
|
|||||||
- `docs/contracts/personal-agent-secondbrain-proposal-route.json`
|
- `docs/contracts/personal-agent-secondbrain-proposal-route.json`
|
||||||
- `docs/contracts/personal-agent-conductor-curator-service-handoff.json`
|
- `docs/contracts/personal-agent-conductor-curator-service-handoff.json`
|
||||||
- `docs/contracts/personal-agent-runtime-readiness-snapshot.json`
|
- `docs/contracts/personal-agent-runtime-readiness-snapshot.json`
|
||||||
|
- `docs/contracts/personal-agent-desktop-exposure-contract.json`
|
||||||
- `docs/prd/2026-06-14-personal-agent-context-runtime-prd.md`
|
- `docs/prd/2026-06-14-personal-agent-context-runtime-prd.md`
|
||||||
- `docs/supersession/2026-06-14-personal-agent-context-runtime-supersession-register.md`
|
- `docs/supersession/2026-06-14-personal-agent-context-runtime-supersession-register.md`
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
{
|
||||||
|
"schema_version": "personal-agent-desktop-exposure-contract/v1",
|
||||||
|
"status": "active-profile-desktop-exposure-contract",
|
||||||
|
"contract_id": "personal-agent-desktop-exposure-contract",
|
||||||
|
"profile_identity": "personal-agent",
|
||||||
|
"display_name": "Steev",
|
||||||
|
"observed_date": "2026-06-14",
|
||||||
|
"desktop_integration_claimed": false,
|
||||||
|
"runtime_readiness_claimed": false,
|
||||||
|
"seed_readiness_claimed": false,
|
||||||
|
"core_promotion_claimed": false,
|
||||||
|
"adapter_workspace": "../cortex-hermes-adapter",
|
||||||
|
"adapter_validator_command": "python3 tools/validate_cortex_hermes_adapter_child.py",
|
||||||
|
"adapter_validator_result_observed": "ok",
|
||||||
|
"adapter_reference_contracts": [
|
||||||
|
"../cortex-hermes-adapter/contracts/desktop-dashboard-host-surface.md",
|
||||||
|
"../cortex-hermes-adapter/contracts/personal-agent-s518-runtime-host-surface-intake.json",
|
||||||
|
"../cortex-hermes-adapter/contracts/first-open-evidence.schema.json",
|
||||||
|
"../cortex-hermes-adapter/dashboard/package-view.sample.json"
|
||||||
|
],
|
||||||
|
"authority_boundary": {
|
||||||
|
"profile_owns_desktop_exposure_contract": true,
|
||||||
|
"adapter_owns_desktop_rendering": true,
|
||||||
|
"seed_owns_package_first_open_proof": true,
|
||||||
|
"core_owns_acceptance": true,
|
||||||
|
"profile_mutates_adapter": false,
|
||||||
|
"notes": "This contract is a profile-side handoff for desktop-visible readiness. It does not wire UI or mutate the adapter workspace."
|
||||||
|
},
|
||||||
|
"allowed_adapter_surfaces": [
|
||||||
|
"package.status",
|
||||||
|
"runtime.health",
|
||||||
|
"onboarding.state",
|
||||||
|
"profile.distribution",
|
||||||
|
"capability.catalog"
|
||||||
|
],
|
||||||
|
"state_vocabulary": [
|
||||||
|
"ready",
|
||||||
|
"degraded",
|
||||||
|
"pending",
|
||||||
|
"blocked",
|
||||||
|
"disabled"
|
||||||
|
],
|
||||||
|
"desktop_rows": [
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.profile",
|
||||||
|
"label": "personal-agent",
|
||||||
|
"display_name": "Steev",
|
||||||
|
"surface": "profile.distribution",
|
||||||
|
"state": "degraded",
|
||||||
|
"source_contract": "docs/contracts/personal-agent-runtime-readiness-snapshot.json",
|
||||||
|
"visible_reason": "Profile exists and capability contracts are present, but aggregate runtime readiness is degraded."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.imessage.read",
|
||||||
|
"label": "iMessage read",
|
||||||
|
"surface": "runtime.health",
|
||||||
|
"state": "ready",
|
||||||
|
"source_contract": "docs/contracts/personal-agent-bluebubbles-binding.json",
|
||||||
|
"visible_reason": "BlueBubbles package validator is OK, read-only, secondbrain-personal, and orgbrain-forbidden."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.mail.read",
|
||||||
|
"label": "Proton Mail read",
|
||||||
|
"surface": "runtime.health",
|
||||||
|
"state": "degraded",
|
||||||
|
"source_contract": "docs/contracts/personal-agent-runtime-readiness-snapshot.json",
|
||||||
|
"visible_reason": "Proton MCP is enabled and bridge is running, but email gate remains exited."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.calendar.read",
|
||||||
|
"label": "Proton Calendar read",
|
||||||
|
"surface": "runtime.health",
|
||||||
|
"state": "degraded",
|
||||||
|
"source_contract": "docs/contracts/personal-agent-runtime-readiness-snapshot.json",
|
||||||
|
"visible_reason": "Calendar gate is running, but Proton/rclone package child and final runtime proof are not complete."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.contacts.read",
|
||||||
|
"label": "Proton Contacts read",
|
||||||
|
"surface": "runtime.health",
|
||||||
|
"state": "degraded",
|
||||||
|
"source_contract": "docs/contracts/personal-agent-runtime-readiness-snapshot.json",
|
||||||
|
"visible_reason": "Proton MCP is enabled, but contacts gate remains exited."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.drive.read",
|
||||||
|
"label": "Proton Drive read",
|
||||||
|
"surface": "runtime.health",
|
||||||
|
"state": "degraded",
|
||||||
|
"source_contract": "docs/contracts/personal-agent-runtime-readiness-snapshot.json",
|
||||||
|
"visible_reason": "rclone about probe is redacted-ok, but governed wrapper and package child are not complete."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.secondbrain.proposal",
|
||||||
|
"label": "Personal memory proposals",
|
||||||
|
"surface": "capability.catalog",
|
||||||
|
"state": "pending",
|
||||||
|
"source_contract": "docs/contracts/personal-agent-secondbrain-proposal-route.json",
|
||||||
|
"visible_reason": "Proposal envelope route exists; durable Secondbrain apply remains blocked."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.browser.host-runtime",
|
||||||
|
"label": "Browser host runtime",
|
||||||
|
"surface": "capability.catalog",
|
||||||
|
"state": "blocked",
|
||||||
|
"source_contract": "docs/prd/2026-06-14-personal-agent-context-runtime-prd.md",
|
||||||
|
"visible_reason": "Full desktop/browser control requires separate PACR-009 approval packet."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"row_id": "personal-agent.write-actions",
|
||||||
|
"label": "Writes and sends",
|
||||||
|
"surface": "capability.catalog",
|
||||||
|
"state": "disabled",
|
||||||
|
"source_contract": "docs/contracts/personal-agent-profile-surface-contract.json",
|
||||||
|
"visible_reason": "Silent sends, deletes, mark-read/read receipts, contact/calendar/file mutation, and durable writes are denied unless a confirmation surface is explicitly approved."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"desktop_false_effects": {
|
||||||
|
"adapter_mutated_by_profile": false,
|
||||||
|
"desktop_or_dashboard_opened": false,
|
||||||
|
"runtime_started": false,
|
||||||
|
"runtime_stopped": false,
|
||||||
|
"docker_started": false,
|
||||||
|
"profile_exposure_changed": false,
|
||||||
|
"memory_domain_access_granted": false,
|
||||||
|
"provider_call": false,
|
||||||
|
"secret_value_read": false,
|
||||||
|
"raw_payload_imported": false,
|
||||||
|
"seed_release_claim": false,
|
||||||
|
"runtime_readiness_claim": false,
|
||||||
|
"public_release_claim": false
|
||||||
|
},
|
||||||
|
"memory_policy": {
|
||||||
|
"target": "secondbrain-personal",
|
||||||
|
"forbidden": [
|
||||||
|
"orgbrain"
|
||||||
|
],
|
||||||
|
"desktop_displays_memory_content": false,
|
||||||
|
"desktop_displays_redacted_state_only": true
|
||||||
|
},
|
||||||
|
"proof_policy": {
|
||||||
|
"mode": "redacted-only",
|
||||||
|
"forbidden_fields": [
|
||||||
|
"raw_messages",
|
||||||
|
"message_text",
|
||||||
|
"mail_bodies",
|
||||||
|
"mail_subjects",
|
||||||
|
"sender_address",
|
||||||
|
"recipient_address",
|
||||||
|
"contact_details",
|
||||||
|
"calendar_event_details",
|
||||||
|
"drive_file_names",
|
||||||
|
"drive_file_contents",
|
||||||
|
"attachment_content",
|
||||||
|
"endpoint_payloads",
|
||||||
|
"credentials",
|
||||||
|
"secret_values"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"remaining_gates": {
|
||||||
|
"adapter_lane_pickup": "blocked-follow-up",
|
||||||
|
"desktop_ui_wiring": "blocked-follow-up",
|
||||||
|
"seed_package_pickup": "blocked-follow-up",
|
||||||
|
"runtime_readiness_finalization": "blocked-follow-up",
|
||||||
|
"browser_host_runtime_approval": "blocked-follow-up",
|
||||||
|
"final_acceptance_packet": "blocked-follow-up"
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -41,7 +41,8 @@ desktop exposure must be treated as one of:
|
|||||||
| Personal-agent Conductor/Curator service handoff | active-authority | `docs/contracts/personal-agent-conductor-curator-service-handoff.json` gives route and hygiene lanes a redacted service map |
|
| Personal-agent Conductor/Curator service handoff | active-authority | `docs/contracts/personal-agent-conductor-curator-service-handoff.json` gives route and hygiene lanes a redacted service map |
|
||||||
| Conductor/curator adoption | blocked-follow-up | Owning lanes must explicitly pick up the handoff; this profile does not mutate them |
|
| Conductor/curator adoption | blocked-follow-up | Owning lanes must explicitly pick up the handoff; this profile does not mutate them |
|
||||||
| Personal-agent runtime readiness snapshot | active-authority | `docs/contracts/personal-agent-runtime-readiness-snapshot.json` names per-surface states and runtime gaps without aggregate readiness claim |
|
| Personal-agent runtime readiness snapshot | active-authority | `docs/contracts/personal-agent-runtime-readiness-snapshot.json` names per-surface states and runtime gaps without aggregate readiness claim |
|
||||||
| Desktop app exposure | blocked-follow-up | `PACR-008`, after adapter lane release |
|
| Personal-agent desktop exposure contract | active-authority | `docs/contracts/personal-agent-desktop-exposure-contract.json` defines adapter-visible rows without UI wiring |
|
||||||
|
| Desktop app exposure wiring | blocked-follow-up | Owning adapter lane must pick up the contract and wire UI after approval |
|
||||||
| Browser/Webwright host control | blocked-follow-up | `PACR-009`, explicit approval only |
|
| Browser/Webwright host control | blocked-follow-up | `PACR-009`, explicit approval only |
|
||||||
|
|
||||||
## Known Artifacts And Supersession State
|
## Known Artifacts And Supersession State
|
||||||
@@ -80,6 +81,7 @@ desktop exposure must be treated as one of:
|
|||||||
- Graph context should expose the personal-agent Secondbrain proposal route as active while keeping durable apply blocked to Secondbrain/curator.
|
- Graph context should expose the personal-agent Secondbrain proposal route as active while keeping durable apply blocked to Secondbrain/curator.
|
||||||
- Graph context should expose the personal-agent Conductor/Curator service handoff as active, while adoption remains blocked to owning lanes.
|
- Graph context should expose the personal-agent Conductor/Curator service handoff as active, while adoption remains blocked to owning lanes.
|
||||||
- Graph context should expose the personal-agent runtime snapshot as degraded until the named runtime gaps close.
|
- Graph context should expose the personal-agent runtime snapshot as degraded until the named runtime gaps close.
|
||||||
|
- Graph context should expose the personal-agent desktop exposure contract as active, while adapter UI wiring remains blocked to the adapter lane.
|
||||||
- Graph context should not treat legacy Cortex Proton/rclone repositories as active authority.
|
- Graph context should not treat legacy Cortex Proton/rclone repositories as active authority.
|
||||||
- Graph context should not treat duplicate Proton skills as separate current product surfaces.
|
- Graph context should not treat duplicate Proton skills as separate current product surfaces.
|
||||||
- Graph context should mark browser/Webwright host control as separate HITL runtime authority.
|
- Graph context should mark browser/Webwright host control as separate HITL runtime authority.
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ REQUIRED = [
|
|||||||
"docs/contracts/personal-agent-secondbrain-proposal-route.json",
|
"docs/contracts/personal-agent-secondbrain-proposal-route.json",
|
||||||
"docs/contracts/personal-agent-conductor-curator-service-handoff.json",
|
"docs/contracts/personal-agent-conductor-curator-service-handoff.json",
|
||||||
"docs/contracts/personal-agent-runtime-readiness-snapshot.json",
|
"docs/contracts/personal-agent-runtime-readiness-snapshot.json",
|
||||||
|
"docs/contracts/personal-agent-desktop-exposure-contract.json",
|
||||||
"docs/prd/2026-06-14-personal-agent-context-runtime-prd.md",
|
"docs/prd/2026-06-14-personal-agent-context-runtime-prd.md",
|
||||||
"docs/issues/2026-06-14-personal-agent-context-runtime-work-orders.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",
|
"docs/supersession/2026-06-14-personal-agent-context-runtime-supersession-register.md",
|
||||||
@@ -130,6 +131,34 @@ REQUIRED_RUNTIME_GAPS = {
|
|||||||
"desktop-adapter-exposure-blocked",
|
"desktop-adapter-exposure-blocked",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REQUIRED_ADAPTER_SURFACES = {
|
||||||
|
"package.status",
|
||||||
|
"runtime.health",
|
||||||
|
"onboarding.state",
|
||||||
|
"profile.distribution",
|
||||||
|
"capability.catalog",
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRED_DESKTOP_STATE_VOCABULARY = {
|
||||||
|
"ready",
|
||||||
|
"degraded",
|
||||||
|
"pending",
|
||||||
|
"blocked",
|
||||||
|
"disabled",
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRED_DESKTOP_ROWS = {
|
||||||
|
"personal-agent.profile",
|
||||||
|
"personal-agent.imessage.read",
|
||||||
|
"personal-agent.mail.read",
|
||||||
|
"personal-agent.calendar.read",
|
||||||
|
"personal-agent.contacts.read",
|
||||||
|
"personal-agent.drive.read",
|
||||||
|
"personal-agent.secondbrain.proposal",
|
||||||
|
"personal-agent.browser.host-runtime",
|
||||||
|
"personal-agent.write-actions",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def read_text(rel: str) -> str:
|
def read_text(rel: str) -> str:
|
||||||
return (ROOT / rel).read_text(encoding="utf-8")
|
return (ROOT / rel).read_text(encoding="utf-8")
|
||||||
@@ -167,6 +196,7 @@ def main() -> int:
|
|||||||
"PACR-005",
|
"PACR-005",
|
||||||
"PACR-006",
|
"PACR-006",
|
||||||
"PACR-007",
|
"PACR-007",
|
||||||
|
"PACR-008",
|
||||||
"status: candidate",
|
"status: candidate",
|
||||||
"owner: jp",
|
"owner: jp",
|
||||||
]:
|
]:
|
||||||
@@ -873,6 +903,142 @@ def main() -> int:
|
|||||||
if remaining_gates.get("reboot_power_loss_drill") != "optional-follow-up":
|
if remaining_gates.get("reboot_power_loss_drill") != "optional-follow-up":
|
||||||
errors.append("runtime_snapshot_reboot_gate_missing")
|
errors.append("runtime_snapshot_reboot_gate_missing")
|
||||||
|
|
||||||
|
desktop = load_json("docs/contracts/personal-agent-desktop-exposure-contract.json", errors)
|
||||||
|
if desktop:
|
||||||
|
if desktop.get("schema_version") != "personal-agent-desktop-exposure-contract/v1":
|
||||||
|
errors.append("desktop_exposure_schema_version_invalid")
|
||||||
|
if desktop.get("status") != "active-profile-desktop-exposure-contract":
|
||||||
|
errors.append("desktop_exposure_status_invalid")
|
||||||
|
if desktop.get("contract_id") != "personal-agent-desktop-exposure-contract":
|
||||||
|
errors.append("desktop_exposure_contract_id_invalid")
|
||||||
|
if desktop.get("profile_identity") != "personal-agent":
|
||||||
|
errors.append("desktop_exposure_profile_identity_not_personal_agent")
|
||||||
|
if desktop.get("display_name") != "Steev":
|
||||||
|
errors.append("desktop_exposure_display_name_not_steev")
|
||||||
|
for key in [
|
||||||
|
"desktop_integration_claimed",
|
||||||
|
"runtime_readiness_claimed",
|
||||||
|
"seed_readiness_claimed",
|
||||||
|
"core_promotion_claimed",
|
||||||
|
]:
|
||||||
|
if desktop.get(key) is not False:
|
||||||
|
errors.append(f"desktop_exposure_overclaim:{key}")
|
||||||
|
if desktop.get("adapter_workspace") != "../cortex-hermes-adapter":
|
||||||
|
errors.append("desktop_exposure_adapter_workspace_invalid")
|
||||||
|
if desktop.get("adapter_validator_command") != "python3 tools/validate_cortex_hermes_adapter_child.py":
|
||||||
|
errors.append("desktop_exposure_adapter_validator_missing")
|
||||||
|
if desktop.get("adapter_validator_result_observed") != "ok":
|
||||||
|
errors.append("desktop_exposure_adapter_validator_not_ok")
|
||||||
|
refs = set(desktop.get("adapter_reference_contracts", []))
|
||||||
|
for ref in [
|
||||||
|
"../cortex-hermes-adapter/contracts/desktop-dashboard-host-surface.md",
|
||||||
|
"../cortex-hermes-adapter/contracts/personal-agent-s518-runtime-host-surface-intake.json",
|
||||||
|
"../cortex-hermes-adapter/contracts/first-open-evidence.schema.json",
|
||||||
|
"../cortex-hermes-adapter/dashboard/package-view.sample.json",
|
||||||
|
]:
|
||||||
|
if ref not in refs:
|
||||||
|
errors.append(f"desktop_exposure_adapter_ref_missing:{ref}")
|
||||||
|
boundary = desktop.get("authority_boundary", {})
|
||||||
|
for key in [
|
||||||
|
"profile_owns_desktop_exposure_contract",
|
||||||
|
"adapter_owns_desktop_rendering",
|
||||||
|
"seed_owns_package_first_open_proof",
|
||||||
|
"core_owns_acceptance",
|
||||||
|
]:
|
||||||
|
if boundary.get(key) is not True:
|
||||||
|
errors.append(f"desktop_exposure_boundary_missing:{key}")
|
||||||
|
if boundary.get("profile_mutates_adapter") is not False:
|
||||||
|
errors.append("desktop_exposure_profile_mutates_adapter")
|
||||||
|
adapter_surfaces = set(desktop.get("allowed_adapter_surfaces", []))
|
||||||
|
if adapter_surfaces != REQUIRED_ADAPTER_SURFACES:
|
||||||
|
errors.append("desktop_exposure_adapter_surfaces_invalid")
|
||||||
|
state_vocabulary = set(desktop.get("state_vocabulary", []))
|
||||||
|
if state_vocabulary != REQUIRED_DESKTOP_STATE_VOCABULARY:
|
||||||
|
errors.append("desktop_exposure_state_vocabulary_invalid")
|
||||||
|
rows = desktop.get("desktop_rows", [])
|
||||||
|
row_ids = {row.get("row_id") for row in rows}
|
||||||
|
missing_rows = sorted(REQUIRED_DESKTOP_ROWS - row_ids)
|
||||||
|
if missing_rows:
|
||||||
|
errors.append(f"desktop_exposure_rows_missing:{','.join(missing_rows)}")
|
||||||
|
state_by_row = {row.get("row_id"): row.get("state") for row in rows}
|
||||||
|
expected_states = {
|
||||||
|
"personal-agent.profile": "degraded",
|
||||||
|
"personal-agent.imessage.read": "ready",
|
||||||
|
"personal-agent.mail.read": "degraded",
|
||||||
|
"personal-agent.calendar.read": "degraded",
|
||||||
|
"personal-agent.contacts.read": "degraded",
|
||||||
|
"personal-agent.drive.read": "degraded",
|
||||||
|
"personal-agent.secondbrain.proposal": "pending",
|
||||||
|
"personal-agent.browser.host-runtime": "blocked",
|
||||||
|
"personal-agent.write-actions": "disabled",
|
||||||
|
}
|
||||||
|
for row_id, expected in expected_states.items():
|
||||||
|
if state_by_row.get(row_id) != expected:
|
||||||
|
errors.append(f"desktop_exposure_row_state_invalid:{row_id}")
|
||||||
|
for row in rows:
|
||||||
|
row_id = row.get("row_id", "<unknown>")
|
||||||
|
if row.get("surface") not in REQUIRED_ADAPTER_SURFACES:
|
||||||
|
errors.append(f"desktop_exposure_row_surface_invalid:{row_id}")
|
||||||
|
if row.get("state") not in REQUIRED_DESKTOP_STATE_VOCABULARY:
|
||||||
|
errors.append(f"desktop_exposure_row_state_not_vocab:{row_id}")
|
||||||
|
if not row.get("source_contract"):
|
||||||
|
errors.append(f"desktop_exposure_row_source_missing:{row_id}")
|
||||||
|
if not row.get("visible_reason"):
|
||||||
|
errors.append(f"desktop_exposure_row_reason_missing:{row_id}")
|
||||||
|
false_effects = desktop.get("desktop_false_effects", {})
|
||||||
|
for effect in [
|
||||||
|
"adapter_mutated_by_profile",
|
||||||
|
"desktop_or_dashboard_opened",
|
||||||
|
"runtime_started",
|
||||||
|
"runtime_stopped",
|
||||||
|
"docker_started",
|
||||||
|
"profile_exposure_changed",
|
||||||
|
"memory_domain_access_granted",
|
||||||
|
"provider_call",
|
||||||
|
"secret_value_read",
|
||||||
|
"raw_payload_imported",
|
||||||
|
"seed_release_claim",
|
||||||
|
"runtime_readiness_claim",
|
||||||
|
"public_release_claim",
|
||||||
|
]:
|
||||||
|
if false_effects.get(effect) is not False:
|
||||||
|
errors.append(f"desktop_exposure_false_effect_not_false:{effect}")
|
||||||
|
memory = desktop.get("memory_policy", {})
|
||||||
|
if memory.get("target") != "secondbrain-personal":
|
||||||
|
errors.append("desktop_exposure_memory_target_not_secondbrain_personal")
|
||||||
|
if "orgbrain" not in memory.get("forbidden", []):
|
||||||
|
errors.append("desktop_exposure_orgbrain_not_forbidden")
|
||||||
|
if memory.get("desktop_displays_memory_content") is not False:
|
||||||
|
errors.append("desktop_exposure_displays_memory_content")
|
||||||
|
if memory.get("desktop_displays_redacted_state_only") is not True:
|
||||||
|
errors.append("desktop_exposure_not_redacted_state_only")
|
||||||
|
forbidden_fields = set(desktop.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"desktop_exposure_forbidden_field_missing:{field}")
|
||||||
|
remaining_gates = desktop.get("remaining_gates", {})
|
||||||
|
for gate in [
|
||||||
|
"adapter_lane_pickup",
|
||||||
|
"desktop_ui_wiring",
|
||||||
|
"seed_package_pickup",
|
||||||
|
"runtime_readiness_finalization",
|
||||||
|
"browser_host_runtime_approval",
|
||||||
|
"final_acceptance_packet",
|
||||||
|
]:
|
||||||
|
if remaining_gates.get(gate) != "blocked-follow-up":
|
||||||
|
errors.append(f"desktop_exposure_remaining_gate_missing:{gate}")
|
||||||
|
|
||||||
for rel in ["AGENT.md", "CONTRACT.md", "DISCLOSURE.md", "README.md", "docs/STEEV-MASTER.md"]:
|
for rel in ["AGENT.md", "CONTRACT.md", "DISCLOSURE.md", "README.md", "docs/STEEV-MASTER.md"]:
|
||||||
path = ROOT / rel
|
path = ROOT / rel
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
@@ -895,6 +1061,7 @@ def main() -> int:
|
|||||||
"Personal-agent Secondbrain proposal route",
|
"Personal-agent Secondbrain proposal route",
|
||||||
"Personal-agent Conductor/Curator service handoff",
|
"Personal-agent Conductor/Curator service handoff",
|
||||||
"Personal-agent runtime readiness snapshot",
|
"Personal-agent runtime readiness snapshot",
|
||||||
|
"Personal-agent desktop exposure contract",
|
||||||
"superseded",
|
"superseded",
|
||||||
"legacy-reference",
|
"legacy-reference",
|
||||||
"blocked-follow-up",
|
"blocked-follow-up",
|
||||||
@@ -910,7 +1077,7 @@ def main() -> int:
|
|||||||
|
|
||||||
result = {
|
result = {
|
||||||
"ok": not errors,
|
"ok": not errors,
|
||||||
"validator": "personal-agent-profile-distribution-v6",
|
"validator": "personal-agent-profile-distribution-v7",
|
||||||
"checked": REQUIRED,
|
"checked": REQUIRED,
|
||||||
"errors": errors,
|
"errors": errors,
|
||||||
"warnings": [],
|
"warnings": [],
|
||||||
|
|||||||
Reference in New Issue
Block a user