Skip to content

shell, ai-host: consent turns script-app agents on and turning an agent off revokes it live (G10, G5) [skip ci] - #159

Merged
ymote merged 1 commit into
mainfrom
fix/g10-g5-consent
Sep 29, 2026
Merged

ymote merged 1 commit into
mainfrom
fix/g10-g5-consent

Conversation

@ymote

@ymote ymote commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

ADR 0004 gap review, G10 and G5 (medium). Follows #157 (G9), rebased on main after #151, #153 and #158; the local checks ran on the rebased tree.

G10: turning an agent off revokes it live; Settings lists every agent

Before, turning an agent off only recorded the answer. A module kept its injected service, and a process app its contexts, until recreated. Settings also listed only apps that had already asked.

  • Revocation. Consent queues every agent turned off: from Settings, or a denial on the first-use sheet. The shell drains the queue whenever approvals change and revokes the live service however the app is hosted:

    • an in-process module's instances lose their assistant, released now (ModuleHost::revoke_assistant);
    • a process app's peer-link contexts close (the app is told agent_turned_off) and its service is released (peer_link::revoke);
    • a contained app's peer is released (contained::revoke).

    Later requests need consent again.

  • Settings lists every app that declares an agent, before it ever asks (apps::agent_apps):

    • native apps whose native-apps.json entry grants octos.*;
    • script apps, system and installed, whose manifest declares octos.*.

G5: script-app agents behind consent

Before, script-app agents were off unless OCTOSENSE_CONTAINED_APPS=1, even with consent, and a peer was granted all four octos.* services.

  • The gate. ai-host has ContainedGate (Off, Consent, Everyone).
    • The shipped policy is Consent: an app gets its agent once consent::granted(app), and its first call asks.
    • OCTOSENSE_CONTAINED_APPS stays the developer override: 1 turns it on for every app without asking, 0 turns it off.
  • Declared services only. A contained app's peer gets only the octos.* services its admitted manifest declares (contained::declared; the shell's lookup is apps::declared_octos, cached per App Hub generation). A call for anything else, or from an app the shell does not know, is refused.

Tests

  • turning_an_agent_off_queues_its_revocation_once
  • turning_the_agent_off_closes_its_contexts_and_releases_its_service (peer link)
  • the module host revokes a live instance's service (in a_granted_module_gets_its_service_at_creation_and_others_get_none)
  • turning_an_agent_off_releases_its_live_peer_at_once (contained, with a fresh peer after)
  • contained_apps_get_only_the_octos_services_their_manifest_declares
  • settings_lists_every_app_that_declares_an_agent_before_it_asks
  • policy_contained_apps_follow_consent

Local checks

These all passed:

  • cargo check for desktop (default and mobile-apps) and for phone (octosense-home --features mobile-apps)
  • cargo test -p octosense-shell --lib on desktop and on phone
  • app-peers (octos-core,ws) and ai-host (octos-core,llm) tests
  • tools/check-shell-graph.sh for both shells
  • tools/setup.py --check --cargo
  • tools/native_apps.py --check

🤖 Generated with Claude Code

…nt off revokes it live (G10, G5) [skip ci]

G10. Turning an agent off in Settings only recorded the answer: a module
kept its injected service, a process app its contexts, until recreated.
And Settings listed only apps that had already asked.

- Consent queues every agent turned off (Settings, or a denial on the
  first-use sheet); the shell drains it whenever approvals change and
  revokes the live service however the app is hosted: an in-process
  module's instances lose their assistant (released now), a process app's
  peer-link contexts close (the app is told `agent_turned_off`) and its
  service is released, a contained app's peer is released.
- Settings lists every app that declares an agent: native apps whose
  native-apps.json entry grants octos.*, and script apps (system and
  installed) whose manifest declares octos.*, before they ever ask.

G5. Script-app agents were off unless OCTOSENSE_CONTAINED_APPS=1, even
with consent, and a peer was granted all four octos.* services.

- ai-host: ContainedGate (Off, Consent, Everyone). The shipped policy is
  Consent: an app gets its agent once consent::granted(app) (the first
  call asks). OCTOSENSE_CONTAINED_APPS stays the developer override (1:
  every app without asking, 0: off).
- A contained app's peer gets only the octos.* services its manifest
  declares (the shell's lookup reads the admitted manifest); a call for
  anything else, or from an app the shell does not know, is refused.

Tests: consent's revocation queue; the peer link closes contexts and
releases the service; the module host revokes a live instance's service;
the contained service releases a live peer and relaunches fresh; declared
services only; Settings lists apps that never asked; the gate's values.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant