Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision 6a996686e010db8c4fa0ac7769b1aa3876e21f0e)
+++ src/routes/activitypub.js	(revision 55eca8b82c97abcf07ed1086c1b4cf60905cc7a8)
@@ -280,4 +280,32 @@
     },
   }));
+  // Inbound REPLIES on your own posts: stored as interactions (the web's
+  // comment machinery), never as mentions, so this read missed them and a
+  // friend's reply arrived everywhere except in your app (Robins melding,
+  // 30-7). Same shape as the other legs; media/quotes ride the stored JSON.
+  const replies = AP.getReplyMessages(auth.site.slug, 60).map((m) => ({
+    id: `${m.object_uri}#create`,
+    type: 'Create',
+    actor: m.actor_uri,
+    published: AP.isoStamp(m.published || m.created_at),
+    object: {
+      id: m.object_uri,
+      type: 'Note',
+      attributedTo: m.actor_uri,
+      content: AP.stripLeadingMentions(m.content),
+      inReplyTo: m.parent_uri || `${base}/ap/notes/${m.post_id}`,
+      published: AP.isoStamp(m.published || m.created_at),
+      to: [me],
+      tag: [{ type: 'Mention', href: me, name: myHandle }, ...(AP.timelineEmojis(m.emoji_json) || [])],
+      attachment: AP.timelineAttachments(m.media_json),
+      'shaer:quote': AP.timelineQuote(m.quote_json),
+      'shaer:author': (m.actor_name || m.actor_handle || m.actor_icon) ? {
+        name: m.actor_name || undefined, handle: m.actor_handle || undefined,
+        icon: m.actor_icon || undefined, url: m.actor_url || undefined,
+        emojis: (() => { try { return m.actor_emoji_json ? JSON.parse(m.actor_emoji_json) : undefined; } catch { return undefined; } })(),
+      } : undefined,
+      'shaer:embed': embedsAllowed ? AP.timelineEmbed(m.embed_json, { playback: playbackAllowed }) : undefined,
+    },
+  }));
   // Your OWN sent notes (replies and direct messages, ap_outbox): without
   // them a reply existed everywhere except in your own app, Messages showed
@@ -295,5 +323,5 @@
   }));
   // Newest first over all legs, so the app can keep treating this as one feed.
-  const items = [...posts, ...messages, ...sent].sort((a, b) => String(b.published || '').localeCompare(String(a.published || '')));
+  const items = [...posts, ...messages, ...replies, ...sent].sort((a, b) => String(b.published || '').localeCompare(String(a.published || '')));
   AP.sendAP(res, {
     '@context': AP.AP_CONTEXT,
Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision 6a996686e010db8c4fa0ac7769b1aa3876e21f0e)
+++ src/services/ActivityPubService.js	(revision 55eca8b82c97abcf07ed1086c1b4cf60905cc7a8)
@@ -2900,4 +2900,24 @@
  * skipped here and stay a post.
  */
+// Inbound replies on YOUR posts, for the app's message stream. They live in
+// ap_interactions (the web's comment machinery) and deliberately NOT in
+// ap_mentions (the mention store returns early for replies-to-us), so the
+// C2S read missed them entirely: a reply arrived at the other side
+// everywhere EXCEPT in the other's app (Robins melding, 30-7: "komt niet
+// binnen bij de ander").
+export function getReplyMessages(slug, limit) {
+  try {
+    return db.prepare(`
+      SELECT i.object_uri, i.actor_uri, i.actor_name, i.actor_handle, i.actor_icon, i.actor_url,
+             i.content, i.published, i.created_at, i.parent_uri, i.post_id,
+             i.emoji_json, i.actor_emoji_json, i.media_json, i.quote_json, i.embed_json
+      FROM ap_interactions i
+      JOIN posts p ON p.id = i.post_id
+      JOIN sites s ON s.id = p.site_id
+      WHERE s.slug = ? AND i.kind = 'reply'
+      ORDER BY COALESCE(i.published, i.created_at) DESC LIMIT ?`).all(slug, limit || 60);
+  } catch { return []; }
+}
+
 export function getDirectMessages(slug, limit) {
   try {
@@ -4200,4 +4220,4 @@
   linkifyBody, bakePostContent, bakePostContentWithMentions, listFollowers, removeFollower, listConnections,
   noteVisibility, belongsInTimeline, playerUrlFor, isRejectedObject, rejectInteraction, interactionReportTarget,
-  getMessages, notificationsSeenAt, ingestOutboxActivity, c2sVisibility, actorDisplay, buildActorRef, prefersEnriched, selfAuthor,
+  getMessages, notificationsSeenAt, ingestOutboxActivity, c2sVisibility, actorDisplay, buildActorRef, prefersEnriched, selfAuthor, getReplyMessages,
 };
Index: test/sent-notes.test.js
===================================================================
--- test/sent-notes.test.js	(revision 6a996686e010db8c4fa0ac7769b1aa3876e21f0e)
+++ test/sent-notes.test.js	(revision 55eca8b82c97abcf07ed1086c1b4cf60905cc7a8)
@@ -44,4 +44,21 @@
 });
 
+test("an inbound reply on your post reaches the app's message stream", () => {
+  // The other half of "komt niet binnen bij de ander": inbound replies live
+  // in ap_interactions (web comments), never in ap_mentions, so the C2S read
+  // never served them. getReplyMessages is the leg that does.
+  db.prepare(`INSERT INTO posts (id, site_id, author_id, slug, title, content, status, published_at, created_at, updated_at)
+              VALUES ('p9','s1','u1','n-p9','', '<p>x</p>','published',datetime('now'),datetime('now'),datetime('now'))`).run();
+  db.prepare(`INSERT INTO ap_interactions (kind, post_id, object_uri, actor_uri, actor_name, actor_handle, content, published, parent_uri, visibility, media_json, created_at)
+              VALUES ('reply','p9','https://unresolvable.invalid/notes/77','https://unresolvable.invalid/u/ness','Ness','@ness@unresolvable.invalid','<p>hoi terug</p>','2026-07-30T12:00:00Z','https://klonkt.test/ap/notes/p9','followers','[{"url":"https://unresolvable.invalid/m/f.jpg","type":"image/jpeg"}]',CURRENT_TIMESTAMP)`).run();
+  const rows = AP.getReplyMessages('me', 60);
+  const r = rows.find((x) => x.object_uri === 'https://unresolvable.invalid/notes/77');
+  assert.ok(r, 'the reply is served for the post owner');
+  assert.equal(r.parent_uri, 'https://klonkt.test/ap/notes/p9', 'threads under the post');
+  assert.equal(r.actor_handle, '@ness@unresolvable.invalid');
+  assert.ok(r.media_json.includes('f.jpg'), 'its media rides along');
+  assert.equal(AP.getReplyMessages('bestaat-niet', 60).length, 0, 'and only for the post owner');
+});
+
 test('a duplicate reply is idempotent success with the SAME id, not a 502', async () => {
   const first = await AP.deliverReply(site, { postId: '', postSlug: null, parent, text: 'nogmaals', visibility: 'friends' });
