From 9fa19b3bd5a8fb7f6bbbc04ce28002fce9476c6a Mon Sep 17 00:00:00 2001 From: Dotta Date: Thu, 3 Sep 2026 06:29:30 -0500 Subject: [PATCH] test(e2e): await terminal comment projection --- tests/runner-e2e/runner.spec.ts | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tests/runner-e2e/runner.spec.ts b/tests/runner-e2e/runner.spec.ts index 49bcf27ce1..21bf2a084a 100644 --- a/tests/runner-e2e/runner.spec.ts +++ b/tests/runner-e2e/runner.spec.ts @@ -1128,7 +1128,8 @@ for (const execution of executions) { planLifecycleEvidence = { interaction, plan }; } - const terminal = await pollUntil({ + const taskMatchers = execution.task.buildMatchers(nonce, execution); + let terminal = await pollUntil({ label: `issue ${issue.id} and heartbeat run terminal state`, deadlineAt, load: loadTaskState, @@ -1139,6 +1140,32 @@ for (const execution of executions) { reject: ({ taskRuns }) => definitiveRunFailure(taskRuns), }); + // Finalization commits the issue/run decision before the derived agent + // comment is guaranteed to be visible through the comments endpoint. + // Give that projection a short consistency window so a successful + // terminal response is not misclassified as an empty provider reply. + // If no comment arrives, retain the original terminal observation and + // let the ordinary message matcher report the product failure. + if (taskMatchers.some((matcher) => matcher.kind.startsWith("message_"))) { + terminal = await pollUntil({ + label: `final agent comment for issue ${issue.id}`, + deadlineAt: Math.min(deadlineAt, Date.now() + 30_000), + load: loadTaskState, + accept: ({ taskRuns, comments }) => { + if (taskRuns.length !== execution.task.expectedRunCount) { + return false; + } + const finalRun = sortRunsChronologically(taskRuns).at(-1); + return comments.some( + (comment) => + comment.createdByRunId === finalRun?.id && + comment.authorAgentId === fixtures!.agent.id, + ); + }, + reject: ({ taskRuns }) => definitiveRunFailure(taskRuns), + }).catch(() => terminal); + } + issue = terminal.currentIssue; selectedRuns = terminal.taskRuns; if (selectedRuns.length !== execution.task.expectedRunCount) { @@ -1386,7 +1413,7 @@ for (const execution of executions) { }, }; matcherResults = await Promise.all( - execution.task.buildMatchers(nonce, execution).map((matcher) => + taskMatchers.map((matcher) => evaluateMatcher(matcher, { ...matcherObservation, // Multi-run tasks intentionally retain earlier waiting/revision