fix question answer sender and self-cancel feedback loop

This commit is contained in:
damocles 2026-05-20 20:29:39 +02:00 committed by Mara
parent e50173f3e1
commit d8e64742f4
3 changed files with 31 additions and 12 deletions

View file

@ -532,6 +532,14 @@ impl Coordinator {
/// events back to the agent that called `ask`, `QuestionAsked`
/// events to the target of a peer question, etc.
pub fn notify_agent(&self, agent: &str, event: &hive_sh4re::HelperEvent) {
self.notify_agent_from(hive_sh4re::SYSTEM_SENDER, agent, event);
}
/// Same as `notify_agent` but with an explicit sender. Use this
/// when the event originates from a known agent or the operator
/// (e.g. `QuestionAnswered` — the answerer should be the `from`,
/// not `system`) so the recipient's terminal shows the right name.
pub fn notify_agent_from(&self, from: &str, agent: &str, event: &hive_sh4re::HelperEvent) {
let body = match serde_json::to_string(event) {
Ok(s) => s,
Err(e) => {
@ -540,7 +548,7 @@ impl Coordinator {
}
};
if let Err(e) = self.broker.send(&hive_sh4re::Message {
from: hive_sh4re::SYSTEM_SENDER.to_owned(),
from: from.to_owned(),
to: agent.to_owned(),
body,
in_reply_to: None,

View file

@ -865,7 +865,8 @@ async fn post_cancel_question(
true,
target.as_deref(),
);
state.coord.notify_agent(
state.coord.notify_agent_from(
hive_sh4re::OPERATOR_RECIPIENT,
&asker,
&hive_sh4re::HelperEvent::QuestionAnswered {
id,

View file

@ -112,7 +112,10 @@ pub fn handle_answer(
.answer(id, answer, answerer)
.map_err(|e| format!("{e:#}"))?;
tracing::info!(%id, %answerer, %asker, "question answered");
coord.notify_agent(
// Use answerer as the broker `from` so the asker's terminal shows
// the real name (agent or "operator") instead of "system".
coord.notify_agent_from(
answerer,
&asker,
&hive_sh4re::HelperEvent::QuestionAnswered {
id,
@ -149,7 +152,13 @@ pub fn handle_cancel_loose_end(
.map_err(|e| format!("{e:#}"))?;
let sentinel = format!("[cancelled by {canceller}]");
tracing::info!(%id, %canceller, %asker, "question cancelled");
coord.notify_agent(
// Only notify the asker if they didn't cancel it themselves.
// Self-cancels are already known to the canceller — sending
// a QuestionAnswered back would cause the harness to process
// its own cancel as an incoming answer.
if asker != canceller {
coord.notify_agent_from(
canceller,
&asker,
&hive_sh4re::HelperEvent::QuestionAnswered {
id,
@ -158,6 +167,7 @@ pub fn handle_cancel_loose_end(
answerer: canceller.to_owned(),
},
);
}
coord.emit_question_resolved(id, &sentinel, canceller, true, target.as_deref());
Ok(())
}