Skip to content

feat(controller-web): show opted-out programs and build programSelection - #178

Merged
peterj merged 1 commit into
feat/program-opt-outfrom
feat/program-opt-out-controller-ui
Oct 19, 2026
Merged

peterj merged 1 commit into
feat/program-opt-outfrom
feat/program-opt-out-controller-ui

Conversation

@ilackarms

Copy link
Copy Markdown
Collaborator

Controller UI for #174. Stacked on #177 (base feat/program-opt-out); this will be rebased onto main after #177 merges.

Changes

Device page

  • ProgramStatus.state gains "opted_out", which the controller already returns from GET /api/v1/devices/{id} for PROGRAM_STATE_OPTED_OUT.
  • The "Managed programs" card shows it as an Opted out neutral badge, with a title saying the device user opted out of this program. The daemon reports no detail for this state, so the badge carries the explanation.

Configuration builder

  • New Program selection section with a "Let device users choose which programs are managed" checkbox.
  • When checked, the generated YAML includes:
    programSelection:
      allowUserChoice: true
    When unchecked, the key is left out. This matches the daemon, which does not serialize the default.
  • While checked, a notice (linked to the checkbox with aria-describedby) warns that daemons predating the setting reject a configuration that contains it, so devices should be upgraded first.
  • Seeded from programSelection.allowUserChoice in /api/v1/daemon-config; DaemonConfigDocument gains programSelection.
  • The .sandbox-compatibility notice style is renamed .config-notice so both sections share it.

Not included: an opted-out hint in the devices list. GET /api/v1/devices (DeviceSummary) carries no per-program state, so it would need a controller query/API change.

Stories

  • Controller/Device details › ProgramOptedOut: a device with an opted-out program; checks the label and title.
  • Controller/Configuration › ActiveProgramSelection (+ DarkProgramSelection): seeded config shows the checkbox checked and the key in the YAML.
  • Controller/Configuration › BuildsProgramSelectionYaml: checking the box adds the key and the upgrade notice; unchecking removes both.

Testing

  • cd frontend && pnpm check passes: Biome, tsc, packaging tests, desktop build, and the Storybook browser tests (desktop-web 59/59, controller-web 71/71, including a11y).

- Device page: the "Managed programs" card labels the `opted_out` state
  "Opted out" with a neutral badge and a title explaining that the device
  user opted out of the program.
- Configuration builder: a "Program selection" section with a "Let device
  users choose which programs are managed" checkbox. When checked, the
  generated YAML includes `programSelection: { allowUserChoice: true }`,
  and a notice warns that daemons predating the setting reject it. The
  checkbox is seeded from the active daemon configuration.
- Rename the `.sandbox-compatibility` notice style to `.config-notice` so
  both sections share it.
- Stories: a device with an opted-out program, a configuration seeded with
  `programSelection`, and an interaction test that toggling the checkbox
  adds and removes the key.

Refs #174
@peterj
peterj requested a balanced review from Copilot October 16, 2026 18:25
@peterj
peterj marked this pull request as ready for review October 16, 2026 18:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused UI changes match the backend contracts, include interaction coverage, and have no unresolved findings.

0 open findings

What changed in this PR

Adds controller UI support for device-user program selection, completing the frontend follow-up to #177.

Changes:

  • Displays opted-out programs with a neutral badge and explanation.
  • Adds a configuration toggle that generates programSelection YAML and warns about older daemons.
  • Adds fixtures and stories covering status display, seeded settings, and toggle behavior.
File Description
frontend/​controller/​src/​views/​DeviceView.tsx Displays the opted-out badge and explanation.
frontend/​controller/​src/​views/​DeviceView.stories.tsx Tests opted-out status display.
frontend/​controller/​src/​views/​ConfigurationView.tsx Adds program selection controls and YAML generation.
frontend/​controller/​src/​views/​ConfigurationView.stories.tsx Tests seeded settings, toggling, and upgrade notices.
frontend/​controller/​src/​types.ts Extends status and configuration types.
frontend/​controller/​src/​styles.css Shares notice styling between configuration sections.
frontend/​controller/​src/​stories/​fixtures.ts Adds opted-out device and program-selection fixtures.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@peterj
peterj merged commit c3c9e8b into feat/program-opt-out Oct 19, 2026
1 check passed
peterj pushed a commit that referenced this pull request Oct 19, 2026
…177)

* feat: let device users choose which configured programs are managed

Add `programSelection.allowUserChoice` to the daemon configuration (off by
default). When it is on, the device user can opt out of every configured
program, or keep only the ones they pick, with `agentdesktop programs set`.

- The daemon stores the choice in its state directory and leaves the
  programs out before every apply, so each provider's existing cleanup
  removes only the files Agentdesktop owns.
- Opted-out programs report a new `opted_out` state (proto, agent,
  controller) on every apply, so admins see it on the device page.
- `GET /v1/programs` and `POST /v1/programs/choice` read and change the
  choice; a change re-applies right away and is reported to the controller.

Refs #174

* fix(agent): keep program choice consistent across reports, --once and sign-in

- Number each apply under the apply lock and publish re-apply outcomes
  through one helper that never replaces a later apply's outcome, so a
  tick that finishes after a program choice change cannot report the old
  choice to the controller.
- Validate `--once` against the chosen programs: an opted-out Copilot CLI
  or VS Code, or an opted-out gateway program, is only cleaned up.
- Start no automatic gateway sign-in (startup, cached and pushed
  configuration) while the device user has opted out of every program
  that uses the gateway and no local LLM proxy runs; opting back in
  starts the device authorization that was skipped.

* feat(controller-web): show opted-out programs and build programSelection (#178)

- Device page: the "Managed programs" card labels the `opted_out` state
  "Opted out" with a neutral badge and a title explaining that the device
  user opted out of the program.
- Configuration builder: a "Program selection" section with a "Let device
  users choose which programs are managed" checkbox. When checked, the
  generated YAML includes `programSelection: { allowUserChoice: true }`,
  and a notice warns that daemons predating the setting reject it. The
  checkbox is seeded from the active daemon configuration.
- Rename the `.sandbox-compatibility` notice style to `.config-notice` so
  both sections share it.
- Stories: a device with an opted-out program, a configuration seeded with
  `programSelection`, and an interaction test that toggling the checkbox
  adds and removes the key.

Refs #174

* feat(desktop): let device users choose managed tools in Settings (#179)

Add a "Managed tools" card to the desktop Settings view, backed by the
daemon's program management API.

- Tauri commands `get_program_management` (GET /v1/programs) and
  `set_program_choice` (POST /v1/programs/choice) relay to the daemon.
- The desktop model polls program management with the existing status
  poll and adds `setProgramChoice`, which shows the choice while saving
  and reports the daemon's error text when it refuses one.
- When the policy allows a choice, the card offers All / Only these /
  None with a switch per configured tool; otherwise it lists the tools
  as managed by the organization. Each tool shows its last apply state,
  including "Opted out".
- Stories cover each state, the choices sent, and the refused case.

Refs #174
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.

3 participants