fix(#1916): direct the agent to end its turn on graceful stop instead of a fenced-empty recv

This commit is contained in:
damocles 2026-06-22 23:19:40 +02:00 committed by mara
commit 1c84b3ef10

View file

@ -84,10 +84,23 @@ impl From<hive_sh4re::Response> for SocketReply {
hive_sh4re::Response::HostJournal { content } => Self::HostJournal(content),
hive_sh4re::Response::Schedules { schedules } => Self::Schedules(schedules),
hive_sh4re::Response::Containers { containers } => Self::Containers(containers),
// A graceful stop is pending — the inbox is fenced. If claude polls
// `recv` during its stop-checkpoint turn, present it as an empty
// inbox (the serve loop is the real handler of this signal).
hive_sh4re::Response::GracefulStop => Self::Messages(Vec::new()),
// A graceful stop is pending — the inbox is fenced. Returning an
// *empty* inbox here is ambiguous: claude's "park on recv" habit
// makes it long-poll again instead of ending the turn, so the
// stop-checkpoint turn never finishes and the drain wait times out
// into a hard stop. Return a single explicit directive instead, so
// every recv during the stop unmissably tells claude to flush + end.
hive_sh4re::Response::GracefulStop => Self::Messages(vec![hive_sh4re::DeliveredMessage {
from: "graceful-stop".into(),
body: "⛔ GRACEFUL STOP IN PROGRESS — the container shuts down as soon as this turn \
ends. Flush anything worth keeping to your durable /state files, then END \
YOUR TURN now. Do NOT call recv again: the inbox is fenced and recv will \
only keep returning this same notice."
.into(),
id: 0,
redelivered: false,
in_reply_to: None,
}]),
hive_sh4re::Response::AgentMeta {
name,
running,