From d40c4ed8945441aa4a7f6eea8a539c865a6b315d Mon Sep 17 00:00:00 2001 From: kenny lopez Date: Mon, 17 Aug 2026 19:03:04 +0100 Subject: [PATCH] Prefer newer agent turn outcomes Signed-off-by: kenny lopez --- .../agent_activity/working_bots_provider.dart | 2 +- .../working_bots_provider_test.dart | 61 ++++++++++++++++++- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/mobile/lib/features/channels/agent_activity/working_bots_provider.dart b/mobile/lib/features/channels/agent_activity/working_bots_provider.dart index fbafe860d8..fc34f9677a 100644 --- a/mobile/lib/features/channels/agent_activity/working_bots_provider.dart +++ b/mobile/lib/features/channels/agent_activity/working_bots_provider.dart @@ -180,10 +180,10 @@ final workingBotPubkeysProvider = Provider.autoDispose }); int _compareComposerTurnRecency(AgentTurnState a, AgentTurnState b) { - if (a.isWorking != b.isWorking) return a.isWorking ? 1 : -1; final activity = a.lastActivityAt.compareTo(b.lastActivityAt); if (activity != 0) return activity; final started = a.startedAt.compareTo(b.startedAt); if (started != 0) return started; + if (a.isWorking != b.isWorking) return a.isWorking ? 1 : -1; return a.turnId.compareTo(b.turnId); } diff --git a/mobile/test/features/channels/agent_activity/working_bots_provider_test.dart b/mobile/test/features/channels/agent_activity/working_bots_provider_test.dart index 9e3901f9ff..af5c1fc381 100644 --- a/mobile/test/features/channels/agent_activity/working_bots_provider_test.dart +++ b/mobile/test/features/channels/agent_activity/working_bots_provider_test.dart @@ -305,8 +305,63 @@ void main() { }); }); - test('prefers live work over retained terminal history', () { + test('prefers a newer terminal outcome over stale working history', () { + final container = ProviderContainer( + overrides: [ + currentPubkeyProvider.overrideWith((ref) => 'owner'), + channelMembersProvider( + _channelId, + ).overrideWith((ref) async => const []), + channelTypingProvider( + _channelId, + ).overrideWith(() => _FakeTypingNotifier(const [])), + agentMentionPubkeysProvider( + _channelId, + ).overrideWith((ref) => const {'agent-a'}), + agentOwnersProvider.overrideWithValue( + const AsyncData({'agent-a': 'owner'}), + ), + userCacheProvider.overrideWith(_FakeUserCacheNotifier.new), + observerRelayProvider.overrideWith( + () => _FakeObserverRelayNotifier({ + 'agent-a': [_observerFrame('agent-a')], + }), + ), + composerAgentTurnStatesProvider.overrideWithValue([ + _turn( + 'agent-a', + turnId: 'turn-old', + startedAt: DateTime.utc(2026, 8, 16, 11, 59), + lastActivityAt: DateTime.utc(2026, 8, 16, 12, 0, 1), + ), + _turn( + 'agent-a', + phase: AgentTurnPhase.error, + turnId: 'turn-new', + startedAt: DateTime.utc(2026, 8, 16, 12), + lastActivityAt: DateTime.utc(2026, 8, 16, 12, 0, 5), + ), + ]), + ], + ); + addTearDown(container.dispose); + + final state = container.read( + composerActivityStateProvider(( + channelId: _channelId, + threadHeadId: null, + )), + ); + + expect(state.agents.single.turnId, 'turn-new'); + expect(state.agents.single.phase, AgentTurnPhase.error); + expect(state.agents.single.isWorking, isFalse); + expect(container.read(workingBotPubkeysProvider(_channelId)), isEmpty); + }); + + test('prefers live work when turn chronology is tied', () { final receiptAt = DateTime.utc(2026, 8, 16, 12, 0, 5); + final startedAt = DateTime.utc(2026, 8, 16, 12, 0, 4); final container = ProviderContainer( overrides: [ currentPubkeyProvider.overrideWith((ref) => 'owner'), @@ -333,13 +388,13 @@ void main() { 'agent-a', phase: AgentTurnPhase.error, turnId: 'turn-old', - startedAt: DateTime.utc(2026, 8, 16, 11, 59), + startedAt: startedAt, lastActivityAt: receiptAt, ), _turn( 'agent-a', turnId: 'turn-new', - startedAt: DateTime.utc(2026, 8, 16, 12, 0, 4), + startedAt: startedAt, lastActivityAt: receiptAt, ), ]),