Summary
After joining a new device, the device list keeps showing the device as Interviewing even though the device is online and the device card (and the actual device) say Online. The two views disagree on the same underlying state.
Root cause
Modern Z2M replaced the legacy boolean pair interviewing / interview_completed on device records in bridge/devices with a single enum field interview_state (PENDING / IN_PROGRESS / SUCCESSFUL / FAILED). The Z2M frontend now reads only interview_state.
Shellbee's Device model only decodes the legacy fields:
Shellbee/Core/Models/Device.swift:16-17,57
On a current Z2M build, a successfully-joined device arrives with interview_state: "SUCCESSFUL" but the legacy interview_completed may be absent or stuck false. That makes the two view layers disagree:
Shellbee/Shared/Components/DeviceCard.swift:302 checks only device.interviewing (false) → shows Online. Accidentally correct.
Shellbee/Features/Devices/DeviceRowView.swift:55 checks device.interviewing || !device.interviewCompleted (true) → shows Interviewing. Wrong against modern Z2M.
Fix
- Add an
interviewState: InterviewState? enum on Device that decodes interview_state.
- Add a single
Device.isInterviewing accessor that prefers interviewState when present and falls back to the legacy pair.
- Replace every existing site that reads the legacy fields directly with the unified accessor (DeviceRowView, DeviceCard, DeviceListView, AppStore+Events, HomeSnapshot, etc.).
- Update the seeder fixtures so the mock bridge emits
interview_state.
Repro
- Pair a new device against a recent Z2M (>= the version that introduced
interview_state).
- Confirm channel and finish pairing.
- Device card → Online. Device list row → Interviewing. Mismatch persists indefinitely.
Summary
After joining a new device, the device list keeps showing the device as Interviewing even though the device is online and the device card (and the actual device) say Online. The two views disagree on the same underlying state.
Root cause
Modern Z2M replaced the legacy boolean pair
interviewing/interview_completedon device records inbridge/deviceswith a single enum fieldinterview_state(PENDING/IN_PROGRESS/SUCCESSFUL/FAILED). The Z2M frontend now reads onlyinterview_state.Shellbee's
Devicemodel only decodes the legacy fields:Shellbee/Core/Models/Device.swift:16-17,57On a current Z2M build, a successfully-joined device arrives with
interview_state: "SUCCESSFUL"but the legacyinterview_completedmay be absent or stuckfalse. That makes the two view layers disagree:Shellbee/Shared/Components/DeviceCard.swift:302checks onlydevice.interviewing(false) → shows Online. Accidentally correct.Shellbee/Features/Devices/DeviceRowView.swift:55checksdevice.interviewing || !device.interviewCompleted(true) → shows Interviewing. Wrong against modern Z2M.Fix
interviewState: InterviewState?enum onDevicethat decodesinterview_state.Device.isInterviewingaccessor that prefersinterviewStatewhen present and falls back to the legacy pair.interview_state.Repro
interview_state).