From b8cbe40c015d6ebe1981ea7771854d6e62cfa9ed Mon Sep 17 00:00:00 2001 From: 777genius Date: Wed, 29 Apr 2026 19:52:56 +0300 Subject: [PATCH] test: stabilize claude stop hook live report check --- .../MemberWorkSyncClaudeStopHook.live.test.ts | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/test/main/services/team/MemberWorkSyncClaudeStopHook.live.test.ts b/test/main/services/team/MemberWorkSyncClaudeStopHook.live.test.ts index 98eb083e..6116e207 100644 --- a/test/main/services/team/MemberWorkSyncClaudeStopHook.live.test.ts +++ b/test/main/services/team/MemberWorkSyncClaudeStopHook.live.test.ts @@ -70,6 +70,19 @@ interface ClaudeStopHookLiveScenario { buildInstructionLines(context: Required): string[]; } +function hasAcceptedReportForScenario(input: { + metrics: Awaited>; + memberName: string; + expectedState: ClaudeStopHookLiveScenarioState; +}): boolean { + return input.metrics.recentEvents.some( + (event) => + event.kind === 'report_accepted' && + event.memberName === input.memberName && + event.reportState === input.expectedState + ); +} + liveDescribe('Member work sync Claude Stop hook live e2e', () => { let tempDir: string; let tempClaudeRoot: string; @@ -314,8 +327,9 @@ liveDescribe('Member work sync Claude Stop hook live e2e', () => { context: 'Claude validation turn', }); await feature!.replayPendingReports([teamName!]); - const [status, tasks] = await Promise.all([ + const [status, metrics, tasks] = await Promise.all([ feature!.getStatus({ teamName: teamName!, memberName }), + feature!.getMetrics({ teamName: teamName! }), new TeamTaskReader().getTasks(teamName!), ]); const currentTask = tasks.find((candidate) => candidate.id === task.id); @@ -323,11 +337,17 @@ liveDescribe('Member work sync Claude Stop hook live e2e', () => { const hasMarkerComment = currentTask?.comments?.some( (comment) => comment.author === memberName && comment.text.includes(expectedMarker) ); + const reportAccepted = + (status.report?.accepted === true && status.report.state === scenario.expectedState) || + hasAcceptedReportForScenario({ + metrics, + memberName, + expectedState: scenario.expectedState, + }); return Boolean( hasMarkerComment && currentTask?.status === scenario.expectedTaskStatus && - status.report?.accepted && - status.report.state === scenario.expectedState + reportAccepted ); }, 300_000, 2_000, async () => formatMemberWorkSyncDiagnostics({ @@ -379,17 +399,34 @@ liveDescribe('Member work sync Claude Stop hook live e2e', () => { feature.getStatus({ teamName, memberName }), feature.getMetrics({ teamName }), ]); - expect(finalStatus.state).toBe(scenario.expectedState); - expect(finalStatus.report).toMatchObject({ - accepted: true, - state: scenario.expectedState, - }); + const finalReportAccepted = + (finalStatus.report?.accepted === true && + finalStatus.report.state === scenario.expectedState) || + hasAcceptedReportForScenario({ + metrics, + memberName, + expectedState: scenario.expectedState, + }); + expect(finalReportAccepted).toBe(true); + if (finalStatus.state !== 'inactive') { + expect(finalStatus.state).toBe(scenario.expectedState); + expect(finalStatus.report).toMatchObject({ + accepted: true, + state: scenario.expectedState, + }); + } if (scenario.expectedState === 'caught_up') { expect(finalStatus.agenda.items).toHaveLength(0); } else { expect(finalStatus.agenda.items.some((item) => item.taskId === task.id)).toBe(true); } - expect(metrics.recentEvents.some((event) => event.kind === 'report_accepted')).toBe(true); + expect( + hasAcceptedReportForScenario({ + metrics, + memberName, + expectedState: scenario.expectedState, + }) + ).toBe(true); await expect(feature.dispatchDueNudges([teamName])).resolves.toMatchObject({ claimed: 0, delivered: 0,