fix(team): hide review pickup escalation rows

This commit is contained in:
777genius 2026-05-09 16:01:20 +03:00
parent fa829f92c8
commit 5d3ec8a8bd
5 changed files with 92 additions and 12 deletions

View file

@ -287,29 +287,42 @@ function buildMemberWorkSyncReviewPickupEscalationText(input: {
}): string { }): string {
const taskLines = input.taskRefs.length const taskLines = input.taskRefs.length
? input.taskRefs ? input.taskRefs
.map( .map((taskRef) => `- ${taskRef.displayId ?? taskRef.taskId.slice(0, 8)}`)
(taskRef) => `- ${taskRef.displayId ?? taskRef.taskId.slice(0, 8)} (${taskRef.taskId})`
)
.join('\n') .join('\n')
: '- No task refs recorded'; : '- No task refs recorded';
const diagnostics = [...new Set(input.diagnostics ?? [])].filter(Boolean); const reasonText = describeMemberWorkSyncReviewPickupEscalationReason(input.reason);
return [ return [
'Review pickup still pending in member work-sync.', 'Review pickup needs lead attention.',
'', '',
`Reviewer: ${input.memberName}`, `Reviewer: ${input.memberName}`,
`Reason: ${input.reason}`, reasonText,
'', '',
'Tasks:', 'Tasks:',
taskLines, taskLines,
'', '',
'No review_start, review_approve, or review_request_changes was recorded for the current review request after the member correction path.', 'No review_start, review_approve, or review_request_changes was recorded for the current review request.',
'Consider reassigning the reviewer or sending a direct instruction.', 'Consider reassigning the reviewer or sending a direct instruction.',
diagnostics.length ? `Diagnostics: ${diagnostics.join(', ')}` : '',
] ]
.filter(Boolean) .filter(Boolean)
.join('\n'); .join('\n');
} }
function describeMemberWorkSyncReviewPickupEscalationReason(reason: string): string {
if (reason.startsWith('provider_not_supported:')) {
return 'Direct review-pickup wake is not available for this member runtime, so the lead needs to handle the stuck review.';
}
if (reason === 'review_pickup_already_delivered_still_stuck') {
return 'A review-pickup reminder was delivered, but the review is still waiting for a review tool action.';
}
if (reason === 'review_pickup_delivery_failed_still_stuck') {
return 'The review-pickup reminder could not be delivered reliably, and the review is still waiting.';
}
if (reason.includes('delivery_port_unavailable')) {
return 'No reliable review-pickup delivery path is available for this member runtime.';
}
return 'The current review request is still waiting for explicit review pickup.';
}
async function createOpenCodeRuntimeAdapterRegistry( async function createOpenCodeRuntimeAdapterRegistry(
reportProgress: (phase: string, message: string) => void = () => undefined reportProgress: (phase: string, message: string) => void = () => undefined
): Promise<TeamRuntimeAdapterRegistry> { ): Promise<TeamRuntimeAdapterRegistry> {

View file

@ -24,7 +24,10 @@ import { filterTeamMessages } from '@renderer/utils/teamMessageFiltering';
import { toMessageKey } from '@renderer/utils/teamMessageKey'; import { toMessageKey } from '@renderer/utils/teamMessageKey';
import { shouldExcludeInboxTextFromReplyCandidates } from '@shared/utils/idleNotificationSemantics'; import { shouldExcludeInboxTextFromReplyCandidates } from '@shared/utils/idleNotificationSemantics';
import { isLeadMember } from '@shared/utils/leadDetection'; import { isLeadMember } from '@shared/utils/leadDetection';
import { isTaskStallRemediationMessage } from '@shared/utils/teamAutomationMessages'; import {
isReviewPickupEscalationMessage,
isTaskStallRemediationMessage,
} from '@shared/utils/teamAutomationMessages';
import { import {
CheckCheck, CheckCheck,
ChevronsDownUp, ChevronsDownUp,
@ -603,6 +606,7 @@ export const MessagesPanel = memo(function MessagesPanel({
(m) => (m) =>
m.messageKind !== 'task_comment_notification' && m.messageKind !== 'task_comment_notification' &&
!isTaskStallRemediationMessage(m) && !isTaskStallRemediationMessage(m) &&
!isReviewPickupEscalationMessage(m) &&
!shouldExcludeInboxTextFromReplyCandidates(typeof m.text === 'string' ? m.text : '') !shouldExcludeInboxTextFromReplyCandidates(typeof m.text === 'string' ? m.text : '')
), ),
[effectiveMessages] [effectiveMessages]

View file

@ -4,7 +4,10 @@ import {
} from '@renderer/utils/bootstrapPromptSanitizer'; } from '@renderer/utils/bootstrapPromptSanitizer';
import { shouldKeepIdleMessageInActivityWhenNoiseHidden } from '@renderer/utils/idleNotificationSemantics'; import { shouldKeepIdleMessageInActivityWhenNoiseHidden } from '@renderer/utils/idleNotificationSemantics';
import { isInboxNoiseMessage } from '@shared/utils/inboxNoise'; import { isInboxNoiseMessage } from '@shared/utils/inboxNoise';
import { isTaskStallRemediationMessage } from '@shared/utils/teamAutomationMessages'; import {
isReviewPickupEscalationMessage,
isTaskStallRemediationMessage,
} from '@shared/utils/teamAutomationMessages';
import { isTeamInternalControlMessageEnvelope } from '@shared/utils/teamInternalControlMessages'; import { isTeamInternalControlMessageEnvelope } from '@shared/utils/teamInternalControlMessages';
import type { InboxMessage } from '@shared/types'; import type { InboxMessage } from '@shared/types';
@ -133,6 +136,7 @@ export function filterTeamMessages(
(m) => (m) =>
m.messageKind !== 'task_comment_notification' && m.messageKind !== 'task_comment_notification' &&
(includeAutomationEvents || !isTaskStallRemediationMessage(m)) && (includeAutomationEvents || !isTaskStallRemediationMessage(m)) &&
!isReviewPickupEscalationMessage(m) &&
!isTeamInternalControlMessageEnvelope(m) !isTeamInternalControlMessageEnvelope(m)
); );
if (timeWindow) { if (timeWindow) {

View file

@ -2,15 +2,26 @@ import type { InboxMessage } from '@shared/types';
type AutomationMessageLike = Pick<InboxMessage, 'from' | 'messageId' | 'messageKind' | 'source'>; type AutomationMessageLike = Pick<InboxMessage, 'from' | 'messageId' | 'messageKind' | 'source'>;
function getMessageId(message: AutomationMessageLike): string {
return typeof message.messageId === 'string' ? message.messageId.trim() : '';
}
export function isTaskStallRemediationMessage(message: AutomationMessageLike): boolean { export function isTaskStallRemediationMessage(message: AutomationMessageLike): boolean {
if (message.messageKind === 'task_stall_remediation') { if (message.messageKind === 'task_stall_remediation') {
return true; return true;
} }
const messageId = typeof message.messageId === 'string' ? message.messageId.trim() : '';
return ( return (
message.source === 'system_notification' && message.source === 'system_notification' &&
message.from === 'system' && message.from === 'system' &&
messageId.startsWith('task-stall:') getMessageId(message).startsWith('task-stall:')
);
}
export function isReviewPickupEscalationMessage(message: AutomationMessageLike): boolean {
return (
message.source === 'system_notification' &&
message.from === 'system' &&
getMessageId(message).startsWith('member-work-sync-review-pickup-escalation:')
); );
} }

View file

@ -585,6 +585,31 @@ Messages:
expect(result.map((message) => message.messageId)).toEqual(['msg-2']); expect(result.map((message) => message.messageId)).toEqual(['msg-2']);
}); });
it('hides review pickup escalation automation rows from conversational message counts by default', () => {
const messages = [
makeMessage({
messageId: 'member-work-sync-review-pickup-escalation:abc123',
from: 'system',
to: 'lead',
source: 'system_notification',
summary: 'Review pickup still pending',
text: 'Review pickup needs lead attention.\n\nReviewer: tom',
}),
makeMessage({
messageId: 'msg-2',
text: 'Visible message',
}),
];
const result = filterTeamMessages(messages, {
timeWindow: null,
filter: { from: new Set(), to: new Set(), showNoise: true },
searchQuery: '',
});
expect(result.map((message) => message.messageId)).toEqual(['msg-2']);
});
it('can include task stall remediation automation rows for the activity timeline', () => { it('can include task stall remediation automation rows for the activity timeline', () => {
const messages = [ const messages = [
makeMessage({ makeMessage({
@ -608,4 +633,27 @@ Messages:
'task-stall:demo:task-a:legacy-epoch', 'task-stall:demo:task-a:legacy-epoch',
]); ]);
}); });
it('keeps review pickup escalation hidden even when regular automation rows are included', () => {
const messages = [
makeMessage({
messageId: 'member-work-sync-review-pickup-escalation:abc123',
from: 'system',
to: 'lead',
source: 'system_notification',
summary: 'Review pickup still pending',
text: 'Review pickup needs lead attention.\n\nReviewer: tom',
}),
];
const result = filterTeamMessages(messages, {
includeAutomationEvents: true,
timeWindow: null,
filter: { from: new Set(), to: new Set(), showNoise: true },
searchQuery: '',
});
expect(result).toEqual([]);
});
}); });