fix(agent): bound push suppression to observed browser attention

This commit is contained in:
2026-10-14 23:06:34 -07:00
parent f534f76b23
commit 5833a0868e
13 changed files with 194 additions and 37 deletions
+75 -4
View File
@@ -70,17 +70,88 @@ test('first source bootstrap never alerts history; later durable candidates debo
const restarted = new AgentPushCoordinator({ ...f.manager.options, warmupMs: 0 }); await restarted.tick(); assert.equal(f.sent.length, 1);
});
test('all tabs veto: visible focused idle, recent interaction and unknown connections; leases eventually expire', async () => {
const f = await fixture(), tab1 = randomUUID(), tab2 = randomUUID(), unknown = randomUUID();
test('all tabs veto while focused; hidden heartbeats and stale sequences cannot extend short transition grace', async () => {
const f = await fixture(), tab1 = randomUUID(), tab2 = randomUUID();
await f.manager.presence(tab1, { sequence: 1, visibility: 'hidden', focused: false, interacted: false });
await f.manager.presence(tab2, { sequence: 1, visibility: 'visible', focused: true, interacted: false });
f.candidate(); await f.manager.tick(); f.advance(2_000); await f.manager.tick(); assert.equal(f.sent.length, 0, 'focused but idle still vetoes');
let receipt = await prisma.agentPushDelivery.findFirstOrThrow();
assert.equal(receipt.lastSuppressionReason, 'foreground_focused'); assert.equal(receipt.lastSuppressionClientKind, 'web');
await f.manager.presence(tab2, { sequence: 2, visibility: 'hidden', focused: false, interacted: true });
f.advance(2_000); await f.manager.tick(); assert.equal(f.sent.length, 0, 'recent input vetoes blur');
await f.manager.presence(tab2, { sequence: 1, visibility: 'visible', focused: true, interacted: false });
assert.equal((await prisma.agentPushPresence.findUniqueOrThrow({ where: { id: tab2 } })).sequence, 2);
await f.manager.connect(unknown); f.advance(31_000); await f.manager.tick(); assert.equal(f.sent.length, 0, 'unknown authenticated socket vetoes');
f.advance(61_000); await f.manager.tick(); assert.equal(f.sent.length, 1, 'expired stale sessions retire');
await f.manager.presence(tab2, { sequence: 3, visibility: 'hidden', focused: false, interacted: true });
f.advance(4_000); await f.manager.tick(); assert.equal(f.sent.length, 1, 'hidden receipts do not renew attention');
receipt = await prisma.agentPushDelivery.findFirstOrThrow();
assert.equal(receipt.lastSuppressionReason, 'inactive_grace'); assert.ok(receipt.lastSuppressedAt);
});
test('blur and visible recent interaction have short grace; fresh focus renews a live lease', async () => {
const f = await fixture(), tab = randomUUID();
await f.manager.presence(tab, { sequence: 1, visibility: 'visible', focused: true, interacted: false });
f.candidate(); await f.manager.tick(); f.advance(2_000);
await f.manager.presence(tab, { sequence: 2, visibility: 'visible', focused: false, interacted: true });
await f.manager.tick(); assert.equal(f.sent.length, 0);
assert.equal((await prisma.agentPushDelivery.findFirstOrThrow()).lastSuppressionReason, 'recent_interaction');
f.advance(3_000); await f.manager.presence(tab, { sequence: 3, visibility: 'visible', focused: false, interacted: false });
f.advance(3_000); await f.manager.tick(); assert.equal(f.sent.length, 1);
await f.manager.presence(tab, { sequence: 4, visibility: 'visible', focused: true, interacted: false });
f.candidate('12'); await f.manager.tick(); f.advance(45_000);
await f.manager.presence(tab, { sequence: 5, visibility: 'visible', focused: true, interacted: false });
f.advance(20_000); await f.manager.tick(); assert.equal(f.sent.length, 1, 'fresh foreground heartbeat extends attention');
f.advance(41_000); await f.manager.tick(); assert.equal(f.sent.length, 2, 'stale focus expires');
});
test('anonymous introduction grace survives heartbeat, new UUID reconnects and coordinator restart without renewing', async () => {
const f = await fixture(), connection = randomUUID();
await f.manager.connect(connection); f.candidate(); await f.manager.tick(); f.advance(2_000); await f.manager.tick();
assert.equal(f.sent.length, 0);
const first = await prisma.agentPushCoordinator.findUniqueOrThrow({ where: { id: 'root' } });
assert.equal((await prisma.agentPushDelivery.findFirstOrThrow()).lastSuppressionReason, 'unknown_client_grace');
await f.manager.heartbeat(connection); await f.manager.disconnect(connection);
await f.manager.connect(randomUUID(), 'web', randomUUID()); f.advance(4_000); await f.manager.tick(); assert.equal(f.sent.length, 1);
f.candidate('12'); await f.manager.tick(); f.advance(2_000);
const restarted = new AgentPushCoordinator({ ...f.manager.options, warmupMs: 0 });
await restarted.connect(randomUUID()); await restarted.tick(); assert.equal(f.sent.length, 2);
assert.deepEqual((await prisma.agentPushCoordinator.findUniqueOrThrow({ where: { id: 'root' } })).unknownSince, first.unknownSince);
// Spending the anonymous budget never disables an independent authenticated browser lease.
await f.manager.presence(randomUUID(), { sequence: 1, visibility: 'visible', focused: true, interacted: false });
f.candidate('13'); await f.manager.tick(); f.advance(2_000); await f.manager.tick(); assert.equal(f.sent.length, 2);
});
test('expired observed web lease is inactive with a live socket; transport heartbeat preserves attribution and never recreates it', async () => {
const f = await fixture(), tab = randomUUID(), connection = randomUUID(), native = randomUUID();
await f.manager.presence(tab, { sequence: 1, visibility: 'visible', focused: true, interacted: false });
await f.manager.connect(connection, 'web', tab); await f.manager.connect(native, 'native');
f.candidate(); await f.manager.tick(); f.advance(61_000);
await f.manager.heartbeat(connection); await f.manager.heartbeat(native); await f.manager.tick(); assert.equal(f.sent.length, 1);
assert.equal((await prisma.agentPushCoordinator.findUniqueOrThrow({ where: { id: 'root' } })).unknownSince, null);
const row = await prisma.agentPushConnection.findUniqueOrThrow({ where: { id: connection } });
assert.equal(row.kind, 'web'); assert.equal(row.sessionId, tab);
assert.equal((await prisma.agentPushConnection.findUniqueOrThrow({ where: { id: native } })).kind, 'native');
await f.manager.disconnect(native); await f.manager.heartbeat(native);
assert.equal(await prisma.agentPushConnection.findUnique({ where: { id: native } }), null);
await f.manager.presence(tab, { sequence: 2, visibility: 'hidden', focused: false, interacted: false });
assert.equal((await prisma.agentPushPresence.findUniqueOrThrow({ where: { id: tab } })).inactiveUntil, null, 'stale focus cannot start fresh grace');
});
test('presence classification cannot borrow a session from a different credential generation', async () => {
const f = await fixture(), tab = randomUUID();
await f.manager.presence(tab, { sequence: 1, visibility: 'hidden', focused: false, interacted: false });
await prisma.agentPushPresence.update({ where: { id: tab }, data: { ownerEpoch: 'another-generation' } });
await f.manager.connect(randomUUID(), 'web', tab); f.candidate(); await f.manager.tick(); f.advance(2_000); await f.manager.tick();
assert.equal(f.sent.length, 0); assert.equal((await prisma.agentPushDelivery.findFirstOrThrow()).lastSuppressionReason, 'unknown_client_grace');
});
test('read at final context refresh cancels without a send and preserves the prior suppression evidence', async () => {
const f = await fixture(); await f.manager.connect(randomUUID()); f.candidate(); await f.manager.tick(); f.advance(2_000); await f.manager.tick();
const prior = await prisma.agentPushDelivery.findFirstOrThrow(), original = f.manager.options.context; let calls = 0;
f.manager.options.context = async (...args) => { if (++calls === 2) await f.manager.advanceRead('11', f.source); return original(...args); };
f.advance(4_000); await f.manager.tick();
const receipt = await prisma.agentPushDelivery.findFirstOrThrow();
assert.equal(f.sent.length, 0); assert.equal(receipt.attempts, 0); assert.equal(receipt.outcome, 'read');
assert.equal(receipt.lastSuppressionReason, prior.lastSuppressionReason); assert.deepEqual(receipt.lastSuppressedAt, prior.lastSuppressedAt);
});
test('instrumented hidden web socket is inactive; missing lease and native-runtime unknown veto', async () => {