Add a self-healing backstop so recovery no longer depends on an event firing:
- periodic reconcile (every 8s): read-only drift check that runs apply ONLY when
broken (no headless / DP-1 not mirroring / workspace trapped on a mirror /
orphan / off-screen window) — no steady-state flicker.
- delayed reconcile 1.5s after a monitor event to catch late workspace
reassignment races.
- socat auto-reconnect; exit cleanly when the session socket vanishes.
New 'reconcile' subcommand. Verified: reconcile heals a deliberately broken
mirror and no-ops on a healthy state.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On swap-back Hyprland brings DP-1 up normal, binds a workspace to it, then apply
mirrors DP-1 — trapping that workspace on a layout-excluded mirror (unreachable;
symptom: 'can't make workspace 1 show'). apply now moves any workspace off a
mirrored output onto the headless primary. Verified the heal operation
(move-off-mirror) manually.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Desktop lives on a persistent HEADLESS output that Sunshine captures; DP-1
mirrors it when present, so streaming works whether or not the physical monitor
is on. Fixes workspace/window orphaning when the monitor powers off (the old
'HEADLESS mirrors DP-1' design collapsed when DP-1 disappeared).
- bin/sunshine-headless-primary.sh: apply (idempotent topology + rescue),
rescue (recenter off-screen floating windows), watch (self-heal on monitor
add/remove and on windows that open off-screen).
- bin/sunshine-prestart.sh: delegates to the manager's apply.
- docs/HEADLESS-PRIMARY.md: full rationale + the ufw stale-subnet gotcha.
Not yet wired into install.sh; configured directly on JARVIS via monitors.conf
and autostart.conf (tracked in the dotfiles repo).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>