feat(input): gate activities on connected input devices (#96) #99

Merged
albert merged 1 commit from u/albert/96/input-dependencies into main 2026-07-19 01:26:14 +00:00
Owner

Add requires_input to entries so an activity is only shown and launchable
while a required class of physical input device is connected — e.g. a typing
tutor on a gaming handheld that appears only once a keyboard is attached.

Supported types: mouse, touch, keyboard, gamepad (camera/mic and MIDI are
future work; the enum is closed so configuring one is a parse error).

  • shepherd-api: InputDeviceType enum + ReasonCode::RequiredInputUnavailable.
  • shepherd-config: requires_input on entries (scalar-or-list, mirrors
    input_compat); sorted/deduped into the validated Entry.
  • shepherd-core: connected_inputs state + set_connected_inputs, and a gate
    in evaluate_entry.
  • shepherdd: new input_devices::InputMonitor — evdev enumeration + hotplug via
    a notify watch on /dev/input, feeding the engine and re-broadcasting
    StateChanged. Only runs when some entry declares requires_input.
  • launcher-ui: reason message + a tooltip naming the missing device(s).

This is a gating condition, distinct from the existing input_compat (a
spawn-time input-translation behaviour that shares the same vocabulary).

Fails open: before the first scan, and when /dev/input isn't readable (the
daemon's user isn't in the input group), gated activities stay visible and a
warning is logged rather than silently hiding content.

Docs in config.example.toml, docs/INSTALL.md, and
docs/ai/history/2026-07-18 001 input-dependencies.md.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01CyP8KhzvqMpRyju5ZiPkLB

Fixes #96

Add `requires_input` to entries so an activity is only shown and launchable while a required class of physical input device is connected — e.g. a typing tutor on a gaming handheld that appears only once a keyboard is attached. Supported types: mouse, touch, keyboard, gamepad (camera/mic and MIDI are future work; the enum is closed so configuring one is a parse error). - shepherd-api: `InputDeviceType` enum + `ReasonCode::RequiredInputUnavailable`. - shepherd-config: `requires_input` on entries (scalar-or-list, mirrors input_compat); sorted/deduped into the validated `Entry`. - shepherd-core: `connected_inputs` state + `set_connected_inputs`, and a gate in `evaluate_entry`. - shepherdd: new `input_devices::InputMonitor` — evdev enumeration + hotplug via a notify watch on /dev/input, feeding the engine and re-broadcasting StateChanged. Only runs when some entry declares `requires_input`. - launcher-ui: reason message + a tooltip naming the missing device(s). This is a gating condition, distinct from the existing `input_compat` (a spawn-time input-translation behaviour that shares the same vocabulary). Fails open: before the first scan, and when /dev/input isn't readable (the daemon's user isn't in the `input` group), gated activities stay visible and a warning is logged rather than silently hiding content. Docs in config.example.toml, docs/INSTALL.md, and docs/ai/history/2026-07-18 001 input-dependencies.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CyP8KhzvqMpRyju5ZiPkLB Fixes #96
feat(input): gate activities on connected input devices (#96)
All checks were successful
CI / Version harmony (pull_request) Successful in 31s
CI / Arch neutrality (pull_request) Successful in 35s
CI / ShellCheck (pull_request) Successful in 38s
CI / CI image (pull_request) Successful in 39s
CI / CI image (Android) (pull_request) Successful in 25s
CI / CI images (pull_request) Successful in 0s
CI / Rustfmt (pull_request) Successful in 57s
CI / E2E (pull_request) Successful in 11m5s
CI / Test (pull_request) Successful in 11m7s
CI / Package (.deb smoke build) (pull_request) Successful in 10m4s
CI / Clippy (pull_request) Successful in 11m4s
CI / Android companion (unit tests) (pull_request) Successful in 1m27s
CI / Android media (cargo-ndk build) (pull_request) Successful in 3m1s
CI / Firewall E2E (pull_request) Successful in 3m36s
CI / Build (pull_request) Successful in 17m47s
78963585e6
Add `requires_input` to entries so an activity is only shown and launchable
while a required class of physical input device is connected — e.g. a typing
tutor on a gaming handheld that appears only once a keyboard is attached.

Supported types: mouse, touch, keyboard, gamepad (camera/mic and MIDI are
future work; the enum is closed so configuring one is a parse error).

- shepherd-api: `InputDeviceType` enum + `ReasonCode::RequiredInputUnavailable`.
- shepherd-config: `requires_input` on entries (scalar-or-list, mirrors
  input_compat); sorted/deduped into the validated `Entry`.
- shepherd-core: `connected_inputs` state + `set_connected_inputs`, and a gate
  in `evaluate_entry`.
- shepherdd: new `input_devices::InputMonitor` — evdev enumeration + hotplug via
  a notify watch on /dev/input, feeding the engine and re-broadcasting
  StateChanged. Only runs when some entry declares `requires_input`.
- launcher-ui: reason message + a tooltip naming the missing device(s).

This is a gating condition, distinct from the existing `input_compat` (a
spawn-time input-translation behaviour that shares the same vocabulary).

Fails open: before the first scan, and when /dev/input isn't readable (the
daemon's user isn't in the `input` group), gated activities stay visible and a
warning is logged rather than silently hiding content.

Docs in config.example.toml, docs/INSTALL.md, and
docs/ai/history/2026-07-18 001 input-dependencies.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CyP8KhzvqMpRyju5ZiPkLB
albert merged commit 80952ad166 into main 2026-07-19 01:26:14 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
albert/shepherd-launcher!99
No description provided.