From 3b6aa6525f97bbd2cfa13fa3541e06cd13e15ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Sat, 23 May 2026 06:43:47 +0000 Subject: [PATCH] test: add failing e2e test for session resume bug (#418) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cross-process resume returns empty text on subsequent prompt. This test documents the bug — expected to fail until #418 is fixed. --- .../__tests__/resume-e2e.test.ts | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 packages/workflow-agent-hermes/__tests__/resume-e2e.test.ts diff --git a/packages/workflow-agent-hermes/__tests__/resume-e2e.test.ts b/packages/workflow-agent-hermes/__tests__/resume-e2e.test.ts new file mode 100644 index 0000000..6305183 --- /dev/null +++ b/packages/workflow-agent-hermes/__tests__/resume-e2e.test.ts @@ -0,0 +1,56 @@ +import { afterEach, describe, expect, it } from "bun:test"; + +import { HermesAcpClient } from "../src/acp-client.js"; + +/** + * E2E test for cross-process session resume. + * + * Simulates the workflow re-entry scenario: + * 1. Client A: connect → prompt → close (developer first run) + * 2. Client B: resume(sessionId) → prompt (developer re-entry after reviewer reject) + * + * This is what happens when uwf thread step spawns uwf-hermes twice for the same role. + */ +describe("HermesAcpClient cross-process resume", () => { + const clients: HermesAcpClient[] = []; + + afterEach(async () => { + for (const c of clients) { + await c.close(); + } + clients.length = 0; + }); + + it( + "resume() after close — second prompt returns non-empty text", + async () => { + // --- Client A: first run --- + const clientA = new HermesAcpClient(); + clients.push(clientA); + + await clientA.connect(process.cwd()); + const first = await clientA.prompt( + "Remember the secret code: WATERMELON. Reply with exactly: ACKNOWLEDGED", + ); + expect(first.text.length).toBeGreaterThan(0); + const sessionId = first.sessionId; + + // Close client A (simulates uwf-hermes process exit) + await clientA.close(); + + // --- Client B: resume (simulates re-entry) --- + const clientB = new HermesAcpClient(); + clients.push(clientB); + + await clientB.resume(sessionId, process.cwd()); + const second = await clientB.prompt( + "What was the secret code I told you earlier? Reply with just the code word.", + ); + + // The critical assertion: resumed session produces non-empty output + expect(second.text.length).toBeGreaterThan(0); + expect(second.sessionId).toBe(sessionId); + }, + { timeout: 3 * 60 * 1000 }, + ); +});