Address review: a superseded Go never opens a second session

An overlay renews its lease right before Go, then captures and uploads
the element before its generate event leaves. When that outlasts the
lease and its result post is lost, a rescuer can claim the target and
Go, and the helper accepted both generate events: two sessions for one
request.

The generate envelope now carries this page's clientId, and the helper
refuses a generate event for a target that another page holds under a
live lease, or that was already answered with a different session
(`served_agent_targets`, recorded on every ok resolution): 409
`agent_target_already_served`, nothing journaled. The overlay treats
that refusal like a foreign session and hands the surface back. The
answering session's own event stays welcome, so the common path (result
post first, then the event) is unchanged.

Tests: two Rust integration cases (rival lease, answered elsewhere,
welcome for the serving session) and a Node protocol case, contract
pins for the envelope and the refusal handling, contract doc.

Written with AI assistance (Claude).

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 b5210471fb
commit 7adb81672d
7 changed files with 186 additions and 6 deletions
+17
View File
@@ -7736,6 +7736,14 @@
}).then(async res => {
if (res.ok) return res;
const body = await res.json().catch(() => ({}));
// The helper refused to open a second session for an agent target
// another page already served (this page's lease lapsed while it was
// capturing): drop the local session and hand the surface back.
if (body.error === 'agent_target_already_served' && msg.type === 'generate'
&& msg.id && msg.id === currentSessionId) {
abandonSupersededGo(msg.id);
return null;
}
// The server refused to journal progress for a session it has never
// seen: this browser is carrying state from another project or a
// wiped store (two apps sharing a localhost port). Continuing to
@@ -7757,6 +7765,14 @@
return sessionCreationGate.then(doSend);
}
function abandonSupersededGo(sessionId) {
if (sessionId !== currentSessionId) return;
console.warn('[impeccable] Another page already served this agent target; clearing session ' + sessionId + '.');
markSessionHandled();
cleanup({ instantChrome: true });
showToast('Another tab already served this request, so this session was cleared.', 6000);
}
let abandonedForeignSessionId = null;
function abandonForeignSession(sessionId) {
if (abandonedForeignSessionId === sessionId || sessionId !== currentSessionId) return;
@@ -8192,6 +8208,7 @@
// as well as from the overlay's own result post.
basePayload.agentTarget = {
targetId: agentTargetForGo.targetId,
clientId: AGENT_TARGET_CLIENT_ID,
result: {
ok: true,
matchCount: agentTargetForGo.matchCount,