Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision 6c152a5a2b3de8369604ab7ceccccad68732ae88)
+++ src/routes/activitypub.js	(revision 6eab7e9673764601cadce6d5f98893e9a32f70a9)
@@ -135,4 +135,7 @@
 queueRoute('follows', (id) => Guardianship.followsCollection(id));
 queueRoute('wards', (id, slug) => Guardianship.wardsCollection(id, slug));
+// Availability (FEP-633c 3.6.1) is never public: the ward reads its
+// guardians' real states here and nowhere else.
+queueRoute('guardians', (id, slug) => Guardianship.guardiansCollection(id, slug));
 
 // ── Inbox read (owner only, AP C2S) ───────────────────────────────
Index: src/routes/guardian.js
===================================================================
--- src/routes/guardian.js	(revision 6c152a5a2b3de8369604ab7ceccccad68732ae88)
+++ src/routes/guardian.js	(revision 6eab7e9673764601cadce6d5f98893e9a32f70a9)
@@ -210,6 +210,10 @@
   const pending = Guardianship.follows.getPending(req.params.id);
   if (!pending) return res.status(404).json({ error: 'gone' });
-  const guardians = Guardianship.listGuardians(pending.ward_slug).map((g) => g.other_uri);
-  if (!guardians.includes(me)) return res.status(403).json({ error: 'not_a_guardian' });
+  const allGuardians = Guardianship.listGuardians(pending.ward_slug).map((g) => g.other_uri);
+  if (!allGuardians.includes(me)) return res.status(403).json({ error: 'not_a_guardian' });
+  // Acting from the dashboard is an answer (3.6), and the quorum runs over
+  // the available set (3.5): both applied here, the same as over the wire.
+  Guardianship.availability.oneAnswer(me, Date.now());
+  const guardians = Guardianship.availability.availableSet(pending.ward_slug, allGuardians, Date.now());
   const r = Guardianship.follows.decide(pending.id, me, decision, guardians);
   try {
