Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision 0db3c72bed823ab28b6f74eedfed3a1cf11faf98)
+++ src/services/ActivityPubService.js	(revision 75f28976575f764e9a39454c608c2d38d027500e)
@@ -3751,5 +3751,7 @@
     id: o.id,
     type: 'Note',
-    attributedTo: actorUri,
+    // De ingesloten actor (shaer-nmw): de byline hoort in attributedTo, waar
+    // elke AP-lezer hem zoekt, en niet in een eigen property ernaast.
+    attributedTo: actorObject(actorUri, actorInfo(authors.get(actorUri), actorUri)),
     inReplyTo: (typeof o.inReplyTo === 'string' ? o.inReplyTo : (o.inReplyTo && o.inReplyTo.id)) || objectUri,
     content: HtmlSanitizerService.sanitize(String(o.content || '').slice(0, 50_000)),
@@ -3777,5 +3779,4 @@
       return out.length ? out : undefined;
     })(),
-    'shaer:author': actorInfo(authors.get(actorUri), actorUri),
   })).sort((a, b) => String(a.published || '').localeCompare(String(b.published || '')));
 
@@ -3802,5 +3803,8 @@
   const kept = [], out = { hidden: 0 };
   for (const n of notes) {
-    if (circle.has(n.attributedTo)) kept.push(n);
+    // actorUriOf, niet n.attributedTo: sinds de byline ingesloten meegaat is
+    // dat een OBJECT en zou een kale vergelijking hier stil alles wegfilteren
+    // -- een ward met een lege thread en nergens een foutmelding.
+    if (circle.has(actorUriOf(n.attributedTo))) kept.push(n);
     else out.hidden += 1;
   }
