Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision f0a33e1fda60c0367aaf75361aa81bcd3e0254f6)
+++ src/services/ActivityPubService.js	(revision 41de7cb2af5077249f1c033243c7dd8dc392d9ab)
@@ -4266,8 +4266,24 @@
 export function conversationHeads(slug) {
   try {
+    // Twee rijen per persoon, niet een: het nieuwste bericht (dat bepaalt waar
+    // iemand in de hemel hangt) EN het nieuwste bericht VAN HEM.
+    //
+    // Die tweede is er omdat het nieuwste bericht van jou kan zijn, en dan
+    // draagt het jouw byline. De hemel zoekt de naam en het gezicht van de
+    // ander in een bericht van de ander -- vond hij dat niet, dan viel hij
+    // terug op het staartje van de actor-uri en heette tante opeens
+    // 'hotelbreakfast'. Op het toestel gezien, 10-8.
+    //
+    // Valt het samen (het nieuwste is al van hem), dan is het een rij; dubbel
+    // sturen doen we niet.
     return db.prepare(`
       SELECT other, stamp, direction, ref FROM (
         SELECT *, ROW_NUMBER() OVER (PARTITION BY other ORDER BY stamp DESC, ref DESC) AS rn
           FROM (${CONVERSATION_UNION})
+      ) WHERE rn = 1
+      UNION
+      SELECT other, stamp, direction, ref FROM (
+        SELECT *, ROW_NUMBER() OVER (PARTITION BY other ORDER BY stamp DESC, ref DESC) AS rn
+          FROM (${CONVERSATION_UNION}) WHERE direction = 'in'
       ) WHERE rn = 1
       ORDER BY stamp DESC, ref DESC`).all({ slug });
Index: test/conversations.test.js
===================================================================
--- test/conversations.test.js	(revision f0a33e1fda60c0367aaf75361aa81bcd3e0254f6)
+++ test/conversations.test.js	(revision 41de7cb2af5077249f1c033243c7dd8dc392d9ab)
@@ -50,5 +50,16 @@
 test('een rij per tegenpartij, hoe druk de drukste ook is', () => {
   const heads = AP.conversationHeads('kind');
-  assert.deepEqual(heads.map((k) => k.other), [OMA, TANTE], 'nieuwste gesprek eerst, allebei aanwezig');
+  assert.deepEqual([...new Set(heads.map((k) => k.other))], [OMA, TANTE], 'nieuwste gesprek eerst, allebei aanwezig');
+});
+
+test('is het nieuwste bericht van MIJ, dan gaat dat van hem ook mee', () => {
+  // Anders draagt het kopje mijn byline en zoekt de hemel de naam en het
+  // gezicht van de ander tevergeefs -- die viel dan terug op het staartje van
+  // de actor-uri. Bij tante is mijn antwoord het nieuwste.
+  const vanTante = AP.conversationHeads('kind').filter((k) => k.other === TANTE);
+  assert.equal(vanTante.length, 2);
+  assert.deepEqual(vanTante.map((k) => k.direction).sort(), ['in', 'out']);
+  // Bij oma is het nieuwste al van haar: dan is een rij genoeg.
+  assert.equal(AP.conversationHeads('kind').filter((k) => k.other === OMA).length, 1);
 });
 
@@ -110,5 +121,11 @@
   const list = await get(`${slug}/conversations`);
   assert.equal(list.status, 200);
-  assert.equal(list.body.totalItems, 2, 'oma en tante, en niet de publieke vreemde');
+  // Drie items voor twee mensen: bij tante gaat haar eigen bericht mee omdat
+  // het nieuwste van mij is (anders mist de hemel haar naam en gezicht).
+  assert.equal(list.body.totalItems, 3);
+  assert.ok(!JSON.stringify(list.body).includes(VREEMDE), 'de publieke vreemde is geen gesprek');
+  const vanTante = list.body.orderedItems.filter((i) => i.actor === TANTE);
+  assert.equal(vanTante.length, 1, 'en dat bericht van tante draagt haar byline');
+  assert.ok(vanTante[0].object.attributedTo.name);
   // De byline zit in de ingesloten actor, net als overal sinds shaer-nmw.
   assert.ok(list.body.orderedItems.every((i) => i.object.attributedTo));
