Surfaced while finishing FEAT-013. The boot-time recovery reconcile (FR-020 / SC-008 / SC-009) is a no-op in the running daemon: `src/agenttower/daemon.py` passes `tmux_list_panes_fn=None` to `reconcile_managed_state_at_boot`, which then skips. T046/T047 are checked complete, but the production recovery path never runs — the same "wired to be called, but with a None backend" pattern T057 (#30) fixed for the spawn path.
Scope
- Build `tmux_list_panes_fn(container_id) -> list[dict]` from the FEAT-004 `TmuxAdapter` (now extended in T057): `resolve_uid` → `list_socket_dir` → `list_panes` per socket → map each pane to the `{tmux_session_name, tmux_pane_index, ...}` shape `recovery.reconcile` consumes.
- Replace the `tmux_list_panes_fn=None` at the daemon-boot call site.
Verification
- Unit-test the channel builder over `FakeTmuxAdapter`.
- Real `py-bench` restart smoke: create layout → simulate daemon restart → surviving panes reattach; a missing pane → `state=failed` + `failed_stage=recovery_reattach`, readable via `app.managed_layout_detail` (SC-009).
Tracked in `specs/013-managed-session-lifecycle/tasks.md` as T058.
Surfaced while finishing FEAT-013. The boot-time recovery reconcile (FR-020 / SC-008 / SC-009) is a no-op in the running daemon: `src/agenttower/daemon.py` passes `tmux_list_panes_fn=None` to `reconcile_managed_state_at_boot`, which then skips. T046/T047 are checked complete, but the production recovery path never runs — the same "wired to be called, but with a None backend" pattern T057 (#30) fixed for the spawn path.
Scope
Verification
Tracked in `specs/013-managed-session-lifecycle/tasks.md` as T058.