Index: src/services/guardianship/handshake.js
===================================================================
--- src/services/guardianship/handshake.js	(revision 3d882bdbd7d45a727ffdcb64eacb870baecdb05d)
+++ src/services/guardianship/handshake.js	(revision 026173008d0d963628475bb6c9caa53d040cea7c)
@@ -341,4 +341,18 @@
     notify(site.slug, { kind: 'offer_rejected', offer: offerId });
     return { status: 202, id: offerId, url: offerId };
+  }
+
+  // §1 is flat in BOTH directions. The Offer path above bars a ward from
+  // offering to guard; this is the mirror: an actor that already guards wards
+  // must not become a ward itself. Only the ward's own accept can create that
+  // state, so the candidate and the existing guardians pass through untouched.
+  //
+  // Without it the inconsistency would also be invisible. actorProps() picks
+  // one role with an if/else and would publish shaer:guardians while dropping
+  // shaer:isGuardian, so this account keeps routing its wards' escalations
+  // locally while every remote §4 check reads it as malformed and drops it —
+  // a ward believing it is watched over when it is not, silent on both sides.
+  if (me === offer.ward_uri && relations.listWards(site.slug).length) {
+    return { status: 403, error: 'a_guardian_cannot_be_guarded' };
   }
 
