Context
src/hardware/pods.ts (PodCapabilities) describes OS-level capability per pod generation (iptables path, python version, DAC socket, package manager). It is keyed by PodVersion (H00 = Pod 3, I00 = Pod 4, J00 = Pod 5).
There is currently no equivalent for cover hardware — cover vibration motor, capSense version, Pillow accessory, etc. The code paths that depend on these implicitly assume the cover variant we've observed in production (Pod 5 J55, cover-only).
Why this hasn't been needed yet
Per docs/adr/0021-alarm-solo-trigger.md, the cover-vibration wire format (ALARM_LEFT/ALARM_RIGHT cmd 5/6 + hex-CBOR) fires the cover motor on both cover-only and Pillow-equipped Pod 5 firmware — the cover motor write runs unconditionally in Sensor.cpp:1221 triggerVibrationAlarm before the pillow path is consulted. So one code path covers every J55 variant we've seen.
We also don't have a known shipped Pod 5 SKU that lacks a cover motor. Every J55 in the wild has one.
When this becomes load-bearing
Add a cover-capability layer the first time one of these appears:
- Pillow accessory exposure — pillow motor is a distinct UART/LSP path. Surfacing Pillow as a controllable accessory (UI, HomeKit) requires runtime detection
- capSense v1 vs v2 sensor parsing — already a real divergence (
docs/hardware/sensor-profiles.md); currently handled implicitly in parsers. Promoting to caps.coverSenseVersion would make intent clearer
- HomeKit accessory advertisement — avoid exposing a "vibration switch" accessory if hardware doesn't have one
- Alarm UI gating — hide intensity slider on a hypothetical coverless variant
- A new cover SKU that doesn't fit the J55 assumptions baked into the alarm code path
Proposed shape (when triggered)
Extend PodCapabilities (or add a sibling CoverCapabilities) with:
interface CoverCapabilities {
hasCoverMotor: boolean
hasPillow: boolean
pillowMotorTransport?: 'uart' | 'lsp'
coverSenseVersion: 1 | 2
}
Detection probably keys off /persistent/deviceinfo/sensor-label + a small DAC probe (frame-shape signature). Source of truth: existing fingerprints in docs/hardware/sensor-profiles.md.
Acceptance (when picked up)
- New
CoverCapabilities type + detection function with unit tests against captured sensor-label fixtures
- One real consumer wired up (Pillow exposure OR capSense version branch) — not just a matrix with one row
- ADR documenting the detection strategy and known variant fingerprints
- Existing alarm path remains variant-agnostic unless a real branch case justifies splitting
Why deferring is correct right now
A capability matrix with one row is premature abstraction. File this so it isn't forgotten, but don't build it until the first real branch appears.
Refs
- ADR 0021 (
docs/adr/0021-alarm-solo-trigger.md) — cover motor write semantics on J55
docs/hardware/sensor-profiles.md — capSense v1/v2 variant fingerprints
src/hardware/pods.ts — current OS-level capability model
Context
src/hardware/pods.ts(PodCapabilities) describes OS-level capability per pod generation (iptables path, python version, DAC socket, package manager). It is keyed byPodVersion(H00 = Pod 3, I00 = Pod 4, J00 = Pod 5).There is currently no equivalent for cover hardware — cover vibration motor, capSense version, Pillow accessory, etc. The code paths that depend on these implicitly assume the cover variant we've observed in production (Pod 5 J55, cover-only).
Why this hasn't been needed yet
Per
docs/adr/0021-alarm-solo-trigger.md, the cover-vibration wire format (ALARM_LEFT/ALARM_RIGHTcmd 5/6 + hex-CBOR) fires the cover motor on both cover-only and Pillow-equipped Pod 5 firmware — the cover motor write runs unconditionally inSensor.cpp:1221 triggerVibrationAlarmbefore the pillow path is consulted. So one code path covers every J55 variant we've seen.We also don't have a known shipped Pod 5 SKU that lacks a cover motor. Every J55 in the wild has one.
When this becomes load-bearing
Add a cover-capability layer the first time one of these appears:
docs/hardware/sensor-profiles.md); currently handled implicitly in parsers. Promoting tocaps.coverSenseVersionwould make intent clearerProposed shape (when triggered)
Extend
PodCapabilities(or add a siblingCoverCapabilities) with:Detection probably keys off
/persistent/deviceinfo/sensor-label+ a small DAC probe (frame-shape signature). Source of truth: existing fingerprints indocs/hardware/sensor-profiles.md.Acceptance (when picked up)
CoverCapabilitiestype + detection function with unit tests against captured sensor-label fixturesWhy deferring is correct right now
A capability matrix with one row is premature abstraction. File this so it isn't forgotten, but don't build it until the first real branch appears.
Refs
docs/adr/0021-alarm-solo-trigger.md) — cover motor write semantics on J55docs/hardware/sensor-profiles.md— capSense v1/v2 variant fingerprintssrc/hardware/pods.ts— current OS-level capability model