Read-only ActivityPub → atproto bridge for the threadiverse using Coves lexicons

outbound: dedupe phrase pinned, cancelled parents decided, poison gated master

Chunk-4 findings 3 + 1 and chunk-9 finding 4 from the second-opinion re-review. - isDuplicate matched ANY 400 whose body contained "already", so Lemmy's genuine rejections (bans, blocks, already_invalid, duplicate_title) went terminal `delivered` — flipping vote state the scores read and opening the causal gate for objects that never landed, with the justifying body discarded. It now matches the received-activity dedupe phrase ("already received", underscore- folded), and the one branch that turns a 400 into a delivered row Debug-logs status + body so a misfire leaves evidence. - The causal gate had verdicts for accepted and poisoned parents but not the third terminal state, cancelled: a child of a cancelled parent looped claim→park at next_attempt=now() with worked=true, a tight 2-UPDATE/3-SELECT spin against Postgres for the full 6h budget. ParentDeliveryPoisoned becomes ParentDeliveryDisposition (open/poisoned/cancelled — cancelled only when EVERY delivery was cancelled and at least one exists, so a pending sibling keeps the parent open and fediverse-origin parents never read as decided); the child poisons as parent_cancelled (redrivable, reason kept — a cancelled child would be unrecoverable and reasonless). The ordinary causal park gains a 1s delay so no future wait path can respin at DB speed, and a parent-lookup store error now parks on the worker's real backoff instead of the causal cadence. - poison() now mirrors countPark: metricPoisoned increments only when the (exists, applied) fence accepted the mark, and a bounced poison Warns — the counter DEPLOY.md tells operators to redrive on no longer counts stale-lease no-ops. New PoisonClassParentCancelled joins neverReachedTheWireClasses, per that file's own contract. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>