diff --git a/src/tracker/ws/manager.py b/src/tracker/ws/manager.py index d87f5cc..1c05982 100644 --- a/src/tracker/ws/manager.py +++ b/src/tracker/ws/manager.py @@ -43,43 +43,43 @@ class ConnectionManager: await self.disconnect(slug) async def broadcast_message(self, project_id: str, message: dict, author_slug: str): - """Broadcast message.new — filtered by chat_listen.""" - logger.info("broadcast_message: project=%s, author=%s, clients=%s", project_id, author_slug, list(self.clients.keys())) - for slug, client in list(self.clients.items()): - logger.info(" checking %s: subscribed=%s, chat_listen=%s", slug, client.subscribed_projects, client.chat_listen) + """Broadcast message.new. Humans get everything, agents filtered by subscription.""" mentions = message.get("mentions", []) for slug, client in list(self.clients.items()): if slug == author_slug: - continue # don't echo to sender + continue + # Humans/bridges get ALL messages — filtering on client side + if client.member_type in ("human", "bridge"): + await self.send_to(slug, {"type": "message.new", "data": message}) + continue + # Agents: check subscription + chat_listen if project_id not in client.subscribed_projects: continue - # Filter by chat_listen if client.chat_listen == "none": - continue # don't send any chat messages + continue if client.chat_listen == "mentions" and slug not in mentions: continue await self.send_to(slug, {"type": "message.new", "data": message}) async def broadcast_task_event(self, project_id: str, event_type: str, data: dict): - """Broadcast task events — filtered by task_listen + ownership.""" + """Broadcast task events. Humans get everything, agents filtered.""" assignee = data.get("assignee_slug") reviewer = data.get("reviewer_slug") watchers = data.get("watchers", []) for slug, client in list(self.clients.items()): + # Humans/bridges get ALL task events + if client.member_type in ("human", "bridge"): + await self.send_to(slug, {"type": event_type, "data": data}) + continue + # Agents: subscription + task_listen filter if project_id not in client.subscribed_projects: continue - - # task_listen: none → skip all task events if client.task_listen == "none": continue - - # task_listen: all → get everything if client.task_listen == "all": await self.send_to(slug, {"type": event_type, "data": data}) continue - - # task_listen: mentions → only if involved if slug in (assignee, reviewer) or slug in watchers: await self.send_to(slug, {"type": event_type, "data": data})