Tasks: bounded per-event retry policy + respawn dead tmux sessions
Phase 3 of 3 (bugfix → design → tasks). DAG — a task starts once its dependencies are checked.
- [x] T1 —
TmuxResult.session_missing. Addsession_missing: bool = FalsetoTmuxResult; set itTrueonTmuxRunner.deliver'shas_session-false early return. (AC7, AC8) - [x] T2 —
Dispatcher.delivery_status. Adddelivery_status(delivery_id, refs) -> "done"|"inflight"|"unhandled"readingrecent_deliveries(done), the dedup cache (inflight), else unhandled. (AC2, AC5) — depends on nothing. - [x] T3 — Respawn on delivery. In
_dispatch_one, when the tmux delivery fails andresult.session_missing, call new_respawn_tmux(session, routed, prompt): reusesession.harness/cwd/tmux_target, mint a new id,tmux.spawnwith the event prompt as boot prompt, re-register (force=True, preservingrecent_deliveries),touch, emitsession.respawned; fail-closed + release on any inability. (AC7, AC9) — depends on T1. - [x] T4 —
polling.maxRetriesconfig. Add to.the-loop/cli-config.schema.json(integer, default 3, min 1) and.the-loop/cli-config.yaml; mirror onPollConfig(from_mapping) and add a--max-retriesflag topoll start. (AC1) - [x] T5 —
PollStateretry ledger. Replace the flat baseline withseenComments(resolved) +commentAttempts+spawn({attempts, gaveUp, deliveryId}); add accessors andfinalize(ref, live_ids, polled_at)pruning both maps to the live thread. Round-trips through the JSON file. (AC2–AC6) - [x] T6 —
_process_itemretry flow. Rewrite to: baseline dropped (unauthorized/self) comments; arm/retry the spawn with the budget (_try_spawn, armed by first sight / new activity / in-progress, re-armed by a new comment); process each unresolved candidate comment viadelivery_status(done→resolve, inflight→wait, unhandled→retry/give-up);finalizeat cycle end. Emitpoll.spawn_failed/poll.comment_failedon give-up and addattempttopoll.comment_forwarded. AddfailurestoPollSummary/poll.cycle. (AC2–AC6) — depends on T2, T4, T5. - [x] T7 — Event types. Register
session.respawned,poll.spawn_failed,poll.comment_failedinEVENT_TYPES; noteattemptonpoll.comment_forwarded. (AC10) — depends on T3, T6. - [x] T8 — Tests. Unit:
session_missing(T1),delivery_status(T2),PollStateledger (T5). Integration: respawn-on-dead-session + no-respawn on other failure (test_tmux_runner_integration.py); comment retry→give-up→ ignore, new-comment-retriggers, success-baselines (test_poller_integration.py/test_poller.py) — Gherkin docstrings + requirement links. (all AC) — depends on T1–T7. - [x] T9 — Capability docs. Update
docs/capabilities/interactive-sessions.md(respawn) anddocs/capabilities/webhook-triggers.md/ the poller capability doc (retry policy) with current behaviour + history rows. - [x] T10 — Gates.
ruff check/ruff format --check,pyright,pytestall green; updateexecution-log.md.