feat(s3/lifecycle): dispatcher + blocker store + per-shard pipeline
Dispatcher consumes due Matches from the schedule, calls LifecycleDelete,
and routes outcomes:
DONE / NOOP_RESOLVED / SKIPPED_OBJECT_LOCK -> Cursor.Advance
RETRY_LATER (within budget) -> re-schedule with backoff
RETRY_LATER (budget exhausted) / BLOCKED -> BlockerStore.Put + Freeze
BlockerStore is a small interface with InMemoryBlockerStore for tests;
the filer-backed impl follows when the worker task registration lands.
Pipeline composes Reader + Router + Dispatcher into a single Run loop
keyed by shard. Cursor is restored on start, blockers are replayed as
freezes, checkpoints write at a configurable cadence, and a final save
fires on shutdown. The meta-log itself is the durable buffer for in-flight
schedule entries — restart re-derives them from the cursor's MinTsNs.