Index: src/services/guardianship/delivery.js
===================================================================
--- src/services/guardianship/delivery.js	(revision c8e03c6553401711c2e513b26dd53e24cc5a9486)
+++ src/services/guardianship/delivery.js	(revision 6d5ce0cde5b3d2911f42fcf2b4cd343d687c8c3b)
@@ -41,5 +41,5 @@
 // call-for-help path).
 export async function deliverDirectNote(site, { recipients, text, language, inReplyTo, attachments, helpRequest, wave, awayUntil }) {
-  const { actorId, fetchActor, deriveHandle, escHtml, linkUrls, linkHashtags,
+  const { actorId, fetchActor, localActor, deliverTo, deriveHandle, escHtml, linkUrls, linkHashtags,
           getOutboxRow, buildReplyNote, AP_CONTEXT, getOrCreateKeys, deliver, enqueueDelivery } = deps;
   const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, '');
@@ -50,7 +50,11 @@
   const resolved = [];
   for (const uri of list) {
-    const a = await fetchActor(uri).catch(() => null);
+    // An actor we host is read from our own database, not fetched from our own
+    // hostname: that request has to leave the machine and come back, and when
+    // it does not, the recipient is silently dropped from the note. Everything
+    // that decides anything still runs below, for local and remote alike.
+    const a = (localActor && localActor(uri)) || await fetchActor(uri).catch(() => null);
     if (!a || !(a.inbox || (a.endpoints && a.endpoints.sharedInbox))) continue;
-    resolved.push({ uri, inbox: (a.endpoints && a.endpoints.sharedInbox) || a.inbox, handle: deriveHandle(uri), url: a.url || uri });
+    resolved.push({ uri, inbox: (a.endpoints && a.endpoints.sharedInbox) || a.inbox, local: !!a.local, handle: deriveHandle(uri), url: a.url || uri });
   }
   if (!resolved.length) return null;
@@ -83,5 +87,15 @@
   const keyId = `${me}#main-key`;
   let delivered = 0;
-  for (const inbox of [...new Set(resolved.map((r) => r.inbox))]) {
+  // A recipient on this machine takes the loopback (deliverToActor), which
+  // hands the Create to the same inbox handler an HTTP POST would reach: the
+  // note is stored, the mention is stored, and a shaer:away on it is applied,
+  // all by the code that does it for everyone else. A hairpin POST to our own
+  // hostname is not that code path, it is a second one that only appears to be.
+  for (const r of resolved.filter((x) => x.local)) {
+    const res = await deliverTo(site, r.uri, create).catch(() => null);
+    if (res && res.delivered) delivered++;
+  }
+  // Remote: one POST per inbox, so two guardians on the same server share it.
+  for (const inbox of [...new Set(resolved.filter((x) => !x.local).map((r) => r.inbox))]) {
     let ok = false;
     try { const st = await deliver(inbox, create, keyId, keys.private_pem); ok = st >= 200 && st < 300; } catch { ok = false; }
Index: src/services/guardianship/handshake.js
===================================================================
--- src/services/guardianship/handshake.js	(revision c8e03c6553401711c2e513b26dd53e24cc5a9486)
+++ src/services/guardianship/handshake.js	(revision 6d5ce0cde5b3d2911f42fcf2b4cd343d687c8c3b)
@@ -219,13 +219,9 @@
     const lp = availability.parseLapse(activity.object);
     if (lp) {
+      // ONE path (Robins regel, 29-7): the ward's server opens, tallies and
+      // enforces, wherever it lives. A local ward is reached by the same
+      // deliverTo, which loops back into the inbox handler; co-location is a
+      // transport detail and never a shortcut past the decision.
       const id = `${me}/lapses/${Date.now().toString(36)}${Math.floor(Math.random() * 1e4).toString(36)}`;
-      const wardSlug = deps.localSlug(lp.ward);
-      if (wardSlug) {
-        const r = availability.openLapse({ id, wardSlug, wardUri: lp.ward, target: lp.target, openedBy: me, now: Date.now() });
-        if (r.error) return { status: r.error === 'not_in_available_set' ? 403 : 409, error: r.error };
-        deps.deliverTo(site, lp.target, { id, type: 'Offer', actor: me, to: [lp.target], object: { type: 'shaer:Lapse', 'shaer:ward': lp.ward, object: lp.target } }).catch(() => { /* best-effort */ });
-        notify(wardSlug, { kind: 'lapse_opened', lapse: id, target: lp.target, set: r.set });
-        return { status: 202, id, url: id, 'shaer:set': r.set, 'shaer:threshold': r.threshold };
-      }
       const offer = { id, type: 'Offer', actor: me, to: [lp.ward], object: { type: 'shaer:Lapse', 'shaer:ward': lp.ward, object: lp.target } };
       const delivered = await fanout(site, [lp.ward], offer);
