Index: .beads/issues.jsonl
===================================================================
--- .beads/issues.jsonl	(revision 0f2d44153a43595ae600b8c834c38189c357a7e2)
+++ .beads/issues.jsonl	(revision 1b1cc89338acb01d612f09ac46cef0274eae8981)
@@ -2,5 +2,5 @@
 {"_type":"issue","id":"prutfolio-src-3fl","title":"Audio: continuous playback breekt na 3-4 tracks (browser-policy / state corruption)","description":"Na fix v1 (next() unconditional play) werkt 1-\u003e2 en 2-\u003e3, maar stopt bij 3-\u003e4. Verdacht: iOS Safari autoplay-policy revoke OF audio element state-corruption na meerdere src changes. Fix: pause()+load()+play() pattern in loadTrack, error-event auto-skip naar volgende, NotAllowedError visuele hint (pulse op play-btn).","status":"open","priority":1,"issue_type":"bug","owner":"robin@roboburr.com","created_at":"2026-05-07T22:38:42Z","created_by":"Robin","updated_at":"2026-05-07T22:38:42Z","dependency_count":0,"dependent_count":0,"comment_count":0}
 {"_type":"issue","id":"prutfolio-src-0tg","title":"Audio: continuous playback fix — next() altijd play() ipv conditional","description":"Bug: next() checkte 'if (isPlaying) play()' maar isPlaying was al false door de pause-event die de browser firet vóór ended. Resultaat: track stopt na 1 keer. Fix: drop de conditional, roep altijd play() aan. Zelfde voor prev(). Bestand: src/assets/js/audio-player.js regels 221-230.","status":"closed","priority":1,"issue_type":"bug","assignee":"Robin","owner":"robin@roboburr.com","created_at":"2026-05-06T22:18:40Z","created_by":"Robin","updated_at":"2026-05-06T22:28:20Z","started_at":"2026-05-06T22:26:37Z","closed_at":"2026-05-06T22:28:20Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
-{"_type":"issue","id":"prutfolio-src-byh","title":"Retry Follow delivery so follows don't get stuck on 'pending'","description":"followActor() inserts the ap_following row as 'pending' and then delivers the signed Follow once, with no retry (unlike deliverCreate, which uses the ap_delivery retry queue). A single transient delivery failure therefore leaves the follow permanently 'pending' — the remote never received it, so no Accept ever comes back.\n\nBuild later:\n- Route the Follow delivery through the existing ap_delivery retry queue (backoff), OR\n- Add a periodic re-send / re-poll for follows still 'pending' after N minutes.\n\nNote: a legitimately locked (manual-approval) account also shows 'pending' until the person approves — that is NOT this bug and must stay pending. Only retry the *delivery*, don't auto-flip status.\n\nWorkaround today: unfollow + follow again sends a fresh Follow.","status":"open","priority":2,"issue_type":"feature","owner":"roboburr@gmail.com","created_at":"2026-06-26T13:36:15Z","created_by":"roboburr","updated_at":"2026-06-26T13:36:15Z","dependency_count":0,"dependent_count":0,"comment_count":0}
+{"_type":"issue","id":"prutfolio-src-byh","title":"Retry Follow delivery so follows don't get stuck on 'pending'","description":"followActor() inserts the ap_following row as 'pending' and then delivers the signed Follow once, with no retry (unlike deliverCreate, which uses the ap_delivery retry queue). A single transient delivery failure therefore leaves the follow permanently 'pending' — the remote never received it, so no Accept ever comes back.\n\nBuild later:\n- Route the Follow delivery through the existing ap_delivery retry queue (backoff), OR\n- Add a periodic re-send / re-poll for follows still 'pending' after N minutes.\n\nNote: a legitimately locked (manual-approval) account also shows 'pending' until the person approves — that is NOT this bug and must stay pending. Only retry the *delivery*, don't auto-flip status.\n\nWorkaround today: unfollow + follow again sends a fresh Follow.","status":"in_progress","priority":2,"issue_type":"feature","assignee":"roboburr","owner":"roboburr@gmail.com","created_at":"2026-06-26T13:36:15Z","created_by":"roboburr","updated_at":"2026-07-01T00:43:31Z","started_at":"2026-07-01T00:43:31Z","dependency_count":0,"dependent_count":0,"comment_count":0}
 {"_type":"issue","id":"prutfolio-src-5gl","title":"Self-heal van de fediverse-cache (ap_timeline) bij ingrijpende updates","description":"Robin (2026-06-26): een self-heal als vaste functie, die getriggerd wordt bij ingrijpende updates -- zodat de fediverse-cache zichzelf repareert na een release waar posts in een flux-window coverless/stale bezorgd kunnen zijn (zoals de Cirkels-op-AP-migratie: gelijktijdige vloot-update + new-follower-backfill -\u003e sommige Creates kwamen zonder cover binnen, en de timeline is een snapshot-op-bezorging die nooit auto-bijwerkt).\n\nAanpak (generaliseer het eenmalige scripts/backfill-cirkel-covers.mjs tot een ingebouwde functie):\n- selfHealTimeline() in ActivityPubService: her-fetch ap_timeline-notes (AP) en werk content + media bij (covers/edits); 404/Tombstone -\u003e rij verwijderen.\n- Versie-gate: constante SELFHEAL_VERSION + app_setting selfheal_done_v\u003cN\u003e. Draait EENMAAL bij boot wanneer N wijzigt. Je bumpt N bij een ingrijpende release.\n- Net als autoMigrateCircles: async, non-blocking, best-effort, GEBOUND (bv. laatste ~50 of rate-limited) zodat het de boot niet belast en geen fetch-storm geeft.\n- Aangeroepen in server.js naast startScheduler/startDeliveryWorker/autoMigrateCircles.\n\nComplementair aan prutfolio-src-ymj (live inkomende Update afhandelen = continue self-heal); dit is het catch-up-vangnet voor wat live gemist is. Hergebruik de coverFrom/fetchNote-helpers uit het backfill-script.","status":"closed","priority":2,"issue_type":"feature","owner":"roboburr@gmail.com","created_at":"2026-06-26T10:00:19Z","created_by":"roboburr","updated_at":"2026-06-26T10:04:54Z","closed_at":"2026-06-26T10:04:54Z","close_reason":"Gebouwd: selfHealTimeline() in ActivityPubService, gegate op selfheal_version vs SELFHEAL_VERSION (draait 1x per bump), aangeroepen in server.js bij boot. Geverifieerd op democirkel (7/20 ververst, 2e reload skipt).","dependency_count":0,"dependent_count":0,"comment_count":0}
 {"_type":"issue","id":"prutfolio-src-8z2","title":"Cirkel-feed: boosts van cirkel-vrienden tonen ZONDER ze opnieuw auto-te-boosten (anti-feedback-loop)","description":"Toekomstige feature: ook boosts (Announce) van accounts in je cirkel tonen in de feed/Cirkel.\n\nKRITIEKE GUARD (Robin 2026-06-26): auto-boost mag NOOIT een binnengekomen boost (Announce) opnieuw boosten -- alleen ORIGINELE posts (Create, geauteurd door het gevolgde account zelf). Anders feedback-loop: A boost X -\u003e B auto-boost A-z\\\"n-boost -\u003e C auto-boost B-z\\\"n-boost -\u003e ...\n\nHuidige status: VEILIG. De auto-boost-hook in handleInbox zit alleen op de Create-tak (top-level post van een gevolgd account), niet op Announce. Announces worden nu niet in ap_timeline opgeslagen, dus boosts worden nog niet getoond.\n\nTe doen zodra we boosts tonen:\n- Inkomende Announce van een gevolgd account opslaan/tonen in de feed (los van Create).\n- Auto-boost EXPLICIET beperken tot Create-van-de-auteur; nooit een Announce her-announcen.\n- Evt. extra dedup: niet auto-boosten wat je zelf al geboost hebt, en geen Announce van een Announce.","status":"closed","priority":2,"issue_type":"feature","owner":"roboburr@gmail.com","created_at":"2026-06-26T09:39:44Z","created_by":"roboburr","updated_at":"2026-06-26T12:01:22Z","closed_at":"2026-06-26T12:01:22Z","close_reason":"Opgelost door het nieuwe model: auto-boost is volledig verwijderd (uitlichten = lokaal), dus geen auto-re-Announce → loop-vrij. Boosts tonen in cirkel = lokaal (se8), geen her-boost.","dependency_count":0,"dependent_count":0,"comment_count":0}
Index: CHANGELOG.de.md
===================================================================
--- CHANGELOG.de.md	(revision 0f2d44153a43595ae600b8c834c38189c357a7e2)
+++ CHANGELOG.de.md	(revision 1b1cc89338acb01d612f09ac46cef0274eae8981)
@@ -5,4 +5,15 @@
 
 ## [Unreleased]
+
+### Behoben
+- **Jemandem zu folgen bleibt nicht mehr hängen.** Eine Follow-Anfrage, deren erste Zustellung
+  fehlschlägt (der andere Server kurz nicht erreichbar), wird jetzt automatisch mit Backoff erneut
+  versucht, statt für immer auf „ausstehend" zu bleiben.
+- **Animierte Video-Cover werden in Feeds korrekt angezeigt.** Sie erscheinen nicht mehr leer in der
+  Rasteransicht.
+- **Cover-Videos sind wieder dekorativ.** Ein Rechtsklick auf ein Cover zeigt das normale Link-Menü
+  statt der Video-Steuerung des Browsers, und Rechtsklick „Speichern" ist bei Covern, Bildern und
+  Videos unterdrückt (leichte Reibung).
+- **Geboostete Beiträge zeigen ihren echten Text** im Zirkel, statt eines „RE: <Link>"-Präfixes.
 
 ## [1.1.0] — 2026-06-30
Index: CHANGELOG.md
===================================================================
--- CHANGELOG.md	(revision 0f2d44153a43595ae600b8c834c38189c357a7e2)
+++ CHANGELOG.md	(revision 1b1cc89338acb01d612f09ac46cef0274eae8981)
@@ -5,4 +5,12 @@
 
 ## [Unreleased]
+
+### Fixed
+- **Following someone no longer gets stuck.** A follow whose first delivery fails (the other server
+  briefly unreachable) is now retried automatically with backoff, instead of staying on "pending" forever.
+- **Animated video covers show correctly in feeds.** They no longer appear blank in the grid view.
+- **Cover videos are decorative again.** Right-clicking a cover gives the normal link menu instead of the
+  browser's video controls, and right-click "Save" is suppressed on covers, images and videos (light friction).
+- **Boosted posts show their real text** in the Circle, instead of a "RE: <link>" prefix.
 
 ## [1.1.0] — 2026-06-30
Index: CHANGELOG.nl.md
===================================================================
--- CHANGELOG.nl.md	(revision 0f2d44153a43595ae600b8c834c38189c357a7e2)
+++ CHANGELOG.nl.md	(revision 1b1cc89338acb01d612f09ac46cef0274eae8981)
@@ -5,4 +5,15 @@
 
 ## [Unreleased]
+
+### Opgelost
+- **Iemand volgen blijft niet meer hangen.** Een volg-verzoek waarvan de eerste bezorging faalt (de
+  andere server even onbereikbaar) wordt nu automatisch opnieuw geprobeerd, in plaats van eeuwig op
+  "in behandeling" te blijven staan.
+- **Geanimeerde video-covers tonen correct in feeds.** Ze verschijnen niet meer als een leeg vak in
+  het raster.
+- **Cover-video's zijn weer decoratief.** Rechtsklikken op een cover geeft het normale link-menu in
+  plaats van de video-bediening van de browser, en rechtsklik "Opslaan" is onderdrukt op covers,
+  afbeeldingen en video's (lichte frictie).
+- **Geboooste posts tonen hun echte tekst** in de Cirkel, in plaats van een "RE: <link>"-prefix.
 
 ## [1.1.0] — 2026-06-30
Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision 0f2d44153a43595ae600b8c834c38189c357a7e2)
+++ src/services/ActivityPubService.js	(revision 1b1cc89338acb01d612f09ac46cef0274eae8981)
@@ -1662,6 +1662,8 @@
   fwStmts().ins.run(site.slug, actor.id, ai.handle, ai.name, ai.icon, ai.url, actor.inbox, followId, 'pending', autoBoost ? 1 : 0);
   const follow = { '@context': AP_CONTEXT, id: followId, type: 'Follow', actor: me, object: actor.id };
-  try { await deliver(actor.inbox, follow, `${me}#main-key`, keys.private_pem); }
-  catch (e) { console.warn('[AP] follow deliver failed:', e.message); }
+  // Deliver via the retry queue: a Follow that fails the first attempt (peer down,
+  // timeout, transient 5xx) is retried with backoff instead of staying stuck on
+  // 'pending' forever — the Accept can only come back once the Follow lands.
+  await deliverWithRetry(site.slug, actor.inbox, follow, `${me}#main-key`, keys.private_pem);
   console.log('[AP] follow', site.slug, '→', actor.id);
   // Follow + feature in one step → backfill their recent posts into the Cirkel right away.
