fix(#1953): route approval helper-events to the submitter, not the root agent

This commit is contained in:
damocles 2026-06-23 20:09:40 +02:00 committed by mara
commit 3618399d94
7 changed files with 187 additions and 73 deletions

View file

@ -21,10 +21,10 @@ use hive_sh4re::{LooseEnd, MANAGER_AGENT};
use crate::coordinator::Coordinator;
/// Open threads pending against `agent`:
/// - pending approvals where this agent is the submitter (only ever
/// true for the manager — sub-agents don't submit approvals — but
/// we keep the rule per-agent so the manager's MCP surface gets
/// the same shape via a different code path);
/// - pending approvals where this agent is the submitter (a parent
/// agent with the `approvals` group submits for its children; the
/// root submits for top-level agents). Legacy rows with no recorded
/// submitter count as the root's;
/// - unanswered questions where `agent` is the asker (waiting on
/// someone) OR the target (owes a reply);
/// - pending reminders this agent scheduled (`owner == self`).
@ -35,20 +35,24 @@ use crate::coordinator::Coordinator;
pub fn for_agent(coord: &Coordinator, agent: &str) -> Result<Vec<LooseEnd>> {
let now = now_unix();
let mut out = Vec::new();
// Approvals are only submitted by the manager today. When that
// expands (e.g. sub-agents propose changes to their own configs),
// teach the approvals table to track the submitter and filter
// here on that column — for now MANAGER_AGENT == sole submitter.
if agent == MANAGER_AGENT {
for a in coord.approvals.pending()? {
out.push(LooseEnd::Approval {
id: a.id,
agent: a.agent,
commit_ref: a.commit_ref,
description: a.description,
age_seconds: saturating_age(now, a.requested_at),
});
// Show each pending approval to the agent that submitted it. The
// submitter column is NULL for rows predating it; those count as
// the root agent's.
for a in coord.approvals.pending()? {
let submitter = coord
.approvals
.submitter_of(a.id)?
.unwrap_or_else(|| MANAGER_AGENT.to_owned());
if submitter != agent {
continue;
}
out.push(LooseEnd::Approval {
id: a.id,
agent: a.agent,
commit_ref: a.commit_ref,
description: a.description,
age_seconds: saturating_age(now, a.requested_at),
});
}
for q in coord.questions.pending_all()? {
let role_match = q.asker == agent || q.target.as_deref() == Some(agent);