Address review: the overlay, not the connection, is the roll-call participant

An EventSource reconnect opens a replacement connection under the same
page-level clientId before the old connection is seen to close, so the
close handler used to retire the reconnected overlay's report and hand
its lease back mid-flight. remove_sse_client now retires a client's word
only when no other connection still carries its id, the roll call counts
distinct overlays (plus id-less connections) instead of raw connections,
and the overlay ignores a replayed target it already handled, so a
reconnect never starts a second claim or a second Go. Covered by two new
HTTP cases in crates/cli/tests/agent_target.rs, a protocol case in
tests/live-agent-target.test.mjs, and the overlay contract suite.

AI-assisted: implemented and tested with Claude Code under maintainer
direction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Abdul Wahab
2026-09-15 05:45:49 +05:00
committed by Abdul Wahab
co-authored by Claude Fable 5
parent d397140a77
commit da403a3410
6 changed files with 135 additions and 4 deletions
+9
View File
@@ -7278,8 +7278,17 @@
}
}
// Targets this page already answered (claimed, declined, or acted on).
// The server replays pending targets to every connection that opens, and
// an EventSource reconnect opens one for a page that already heard the
// target, so a replay must not start a second claim or a second Go.
const agentTargetsSeen = [];
function handleAgentTarget(msg) {
if (!msg || typeof msg.targetId !== 'string') return;
if (agentTargetsSeen.includes(msg.targetId)) return;
agentTargetsSeen.push(msg.targetId);
if (agentTargetsSeen.length > 100) agentTargetsSeen.shift();
const busy = agentTargetBusyReason();
if (busy) {
// Roll call: a busy tab reports itself and never acts. The server