From ac2b6c93526ef0350734edc84d1ecf2f45ccbb87 Mon Sep 17 00:00:00 2001 From: 777genius Date: Wed, 6 May 2026 18:59:54 +0300 Subject: [PATCH] fix(team): recognize native bootstrap control envelopes --- .../utils/bootstrapPromptSanitizer.ts | 4 +-- .../utils/teamInternalControlMessages.ts | 13 ++++++- .../team/TeamMessageFeedService.test.ts | 25 ++++++++++++- .../utils/bootstrapPromptSanitizer.test.ts | 21 ++++++++++- .../utils/teamMessageFiltering.test.ts | 21 ++++++++++- .../utils/teamInternalControlMessages.test.ts | 35 +++++++++++++++++++ 6 files changed, 113 insertions(+), 6 deletions(-) diff --git a/src/renderer/utils/bootstrapPromptSanitizer.ts b/src/renderer/utils/bootstrapPromptSanitizer.ts index 64538dc6..20576cd7 100644 --- a/src/renderer/utils/bootstrapPromptSanitizer.ts +++ b/src/renderer/utils/bootstrapPromptSanitizer.ts @@ -135,7 +135,7 @@ export interface InternalControlMessageDisplay { } export function getInternalControlMessageDisplay( - message: Pick & Partial> + message: Pick & Partial> ): InternalControlMessageDisplay | null { if (!isTeamInternalControlMessageEnvelope(message)) { return null; @@ -237,7 +237,7 @@ export function getBootstrapAcknowledgementDisplay( } export function getSanitizedInboxMessageText( - message: Pick & Partial> + message: Pick & Partial> ): string { return ( getInternalControlMessageDisplay(message)?.body ?? diff --git a/src/shared/utils/teamInternalControlMessages.ts b/src/shared/utils/teamInternalControlMessages.ts index 2c2899aa..ee3e5c88 100644 --- a/src/shared/utils/teamInternalControlMessages.ts +++ b/src/shared/utils/teamInternalControlMessages.ts @@ -8,6 +8,7 @@ const INTERNAL_CONTROL_MESSAGE_SOURCES = new Set([ 'runtime_delivery', 'system_notification', ]); +const INTERNAL_BOOTSTRAP_AUTHORS = new Set(['team-lead', 'lead', 'orchestrator']); export function stripTranscriptSpeakerPrefix(value: string): string { let normalized = value.trim(); @@ -22,7 +23,7 @@ export function stripTranscriptSpeakerPrefix(value: string): string { export function isNativeAppManagedBootstrapCheckText(value: unknown): boolean { return ( typeof value === 'string' && - stripTranscriptSpeakerPrefix(value).includes(NATIVE_APP_MANAGED_BOOTSTRAP_CHECK_OPEN) + stripTranscriptSpeakerPrefix(value).startsWith(NATIVE_APP_MANAGED_BOOTSTRAP_CHECK_OPEN) ); } @@ -56,7 +57,17 @@ export function isTeamInternalControlMessageText(value: unknown): boolean { export function isTeamInternalControlMessageEnvelope(message: { text?: unknown; source?: unknown; + from?: unknown; }): boolean { + if (isNativeAppManagedBootstrapCheckText(message.text)) { + if (typeof message.source === 'string') { + return INTERNAL_CONTROL_MESSAGE_SOURCES.has(message.source); + } + return ( + typeof message.from === 'string' && + INTERNAL_BOOTSTRAP_AUTHORS.has(message.from.trim().toLowerCase()) + ); + } if (!isTeamInternalControlMessageText(message.text)) { return false; } diff --git a/test/main/services/team/TeamMessageFeedService.test.ts b/test/main/services/team/TeamMessageFeedService.test.ts index f28d349c..6afdbd28 100644 --- a/test/main/services/team/TeamMessageFeedService.test.ts +++ b/test/main/services/team/TeamMessageFeedService.test.ts @@ -79,8 +79,10 @@ describe('TeamMessageFeedService', () => { getConfig: vi.fn(async () => config), getInboxMessages: vi.fn(async () => [ makeMessage({ + from: 'team-lead', + to: undefined, messageId: 'native-bootstrap-private-check', - source: 'system_notification', + source: undefined, text: '\nprivate\n', }), makeMessage({ @@ -123,6 +125,27 @@ Messages: expect(feed.messages.map((message) => message.messageId)).toEqual(['quoted-control-prompt']); }); + it('does not hide user-authored native bootstrap marker quotes from the feed', async () => { + const service = new TeamMessageFeedService({ + getConfig: vi.fn(async () => config), + getInboxMessages: vi.fn(async () => [ + makeMessage({ + messageId: 'quoted-native-bootstrap-control', + source: 'user_sent', + text: '\nquoted\n', + }), + ]), + getLeadSessionMessages: vi.fn(async () => []), + getSentMessages: vi.fn(async () => []), + }); + + const feed = await service.getFeed('signal-ops-4'); + + expect(feed.messages.map((message) => message.messageId)).toEqual([ + 'quoted-native-bootstrap-control', + ]); + }); + it('refreshes the durable feed after cache expiry even when the dirty signal was missed', async () => { let inboxMessages: InboxMessage[] = [makeMessage()]; const getInboxMessages = vi.fn(async () => inboxMessages); diff --git a/test/renderer/utils/bootstrapPromptSanitizer.test.ts b/test/renderer/utils/bootstrapPromptSanitizer.test.ts index 5220eb80..47d580c6 100644 --- a/test/renderer/utils/bootstrapPromptSanitizer.test.ts +++ b/test/renderer/utils/bootstrapPromptSanitizer.test.ts @@ -71,13 +71,32 @@ Do NOT send acknowledgement-only messages such as "ready" or "online".`); ` Your Agent Teams startup context was already loaded by the app. `, - { source: 'system_notification' } + { source: undefined } ); expect(getInternalControlMessageDisplay(message)?.summary).toBe('Internal bootstrap check'); expect(getSanitizedInboxMessageText(message)).toBe('Internal bootstrap check hidden in the UI.'); }); + it('does not sanitize user-authored native bootstrap marker quotes', () => { + const text = ` +Your Agent Teams startup context was already loaded by the app. +`; + const message = makeMessage(text, { from: 'user', source: 'user_sent' }); + + expect(getInternalControlMessageDisplay(message)).toBeNull(); + expect(getSanitizedInboxMessageText(message)).toBe(text); + }); + + it('does not sanitize visible lead text that only mentions the native bootstrap marker', () => { + const text = + 'Visible note quoting for diagnostics.'; + const message = makeMessage(text, { from: 'team-lead', source: 'lead_process' }); + + expect(getInternalControlMessageDisplay(message)).toBeNull(); + expect(getSanitizedInboxMessageText(message)).toBe(text); + }); + it('sanitizes leaked lead inbox relay prompts defensively', () => { const message = makeMessage( `Human: You have new inbox messages addressed to you (team lead "team-lead"). diff --git a/test/renderer/utils/teamMessageFiltering.test.ts b/test/renderer/utils/teamMessageFiltering.test.ts index 503132b8..0b079e9d 100644 --- a/test/renderer/utils/teamMessageFiltering.test.ts +++ b/test/renderer/utils/teamMessageFiltering.test.ts @@ -41,7 +41,7 @@ describe('filterTeamMessages', () => { const messages = [ makeMessage({ messageId: 'native-bootstrap-private-check', - source: 'system_notification', + source: undefined, text: '\nprivate\n', }), makeMessage({ @@ -59,6 +59,25 @@ describe('filterTeamMessages', () => { expect(result.map((message) => message.messageId)).toEqual(['visible-message']); }); + it('keeps user-authored native bootstrap marker quotes visible', () => { + const messages = [ + makeMessage({ + from: 'user', + messageId: 'user-native-bootstrap-quote', + source: 'user_sent', + text: '\nquoted\n', + }), + ]; + + const result = filterTeamMessages(messages, { + timeWindow: null, + filter: { from: new Set(), to: new Set(), showNoise: true }, + searchQuery: '', + }); + + expect(result.map((message) => message.messageId)).toEqual(['user-native-bootstrap-quote']); + }); + it('hides leaked lead inbox relay prompt echoes', () => { const messages = [ makeMessage({ diff --git a/test/shared/utils/teamInternalControlMessages.test.ts b/test/shared/utils/teamInternalControlMessages.test.ts index 334ed5f7..d537a737 100644 --- a/test/shared/utils/teamInternalControlMessages.test.ts +++ b/test/shared/utils/teamInternalControlMessages.test.ts @@ -18,6 +18,9 @@ Messages: Timestamp: 2026-05-06T15:02:54.853Z Text: #f8d7235a done.`; +const nativeBootstrapPrompt = ` +Your Agent Teams startup context was already loaded by the app. +`; describe('teamInternalControlMessages', () => { it('detects lead inbox relay prompts and Human-prefixed echoes', () => { @@ -60,6 +63,38 @@ describe('teamInternalControlMessages', () => { text: `Human: ${leadRelayPrompt}`, }) ).toBe(false); + expect( + isTeamInternalControlMessageEnvelope({ + text: nativeBootstrapPrompt, + from: 'team-lead', + }) + ).toBe(true); + expect( + isTeamInternalControlMessageEnvelope({ + text: nativeBootstrapPrompt, + from: 'orchestrator', + }) + ).toBe(true); + expect(isTeamInternalControlMessageText(`Human: ${nativeBootstrapPrompt}`)).toBe(true); + expect( + isTeamInternalControlMessageEnvelope({ + source: 'lead_process', + text: `Visible note quoting ${nativeBootstrapPrompt}`, + }) + ).toBe(false); + expect( + isTeamInternalControlMessageEnvelope({ + source: 'user_sent', + text: nativeBootstrapPrompt, + from: 'user', + }) + ).toBe(false); + expect( + isTeamInternalControlMessageEnvelope({ + text: nativeBootstrapPrompt, + from: 'user', + }) + ).toBe(false); }); it('strips an exact echoed control prefix while preserving visible trailing text', () => {