



























@@ -83,6 +83,12 @@ function captureDiagnosticEvents(): {
8383return { events, unsubscribe };
8484}
858586+function mockCallArg<T>(mock: { mock: { calls: unknown[][] } }, index = 0): T {
87+const call = mock.mock.calls[index];
88+expect(call).toBeDefined();
89+return call[0] as T;
90+}
91+8692describe("AgentHarness V2 compatibility adapter", () => {
8793afterEach(() => {
8894resetDiagnosticEventsForTest();
@@ -125,15 +131,14 @@ describe("AgentHarness V2 compatibility adapter", () => {
125131throw new Error("expected started session during successful cleanup");
126132}
127133events.push(`cleanup:${session.lifecycleState}`);
128-expect(cleanupResult).toMatchObject({ agentHarnessId: "native-v2" });
134+expect((cleanupResult as { agentHarnessId?: string }).agentHarnessId).toBe("native-v2");
129135expect(error).toBeUndefined();
130136},
131137};
132138133-await expect(runAgentHarnessV2LifecycleAttempt(harness, params)).resolves.toMatchObject({
134-agentHarnessId: "native-v2",
135-sessionIdUsed: "session-1",
136-});
139+const attemptResult = await runAgentHarnessV2LifecycleAttempt(harness, params);
140+expect((attemptResult as { agentHarnessId?: string }).agentHarnessId).toBe("native-v2");
141+expect(attemptResult.sessionIdUsed).toBe("session-1");
137142expect(events).toEqual([
138143"prepare",
139144"start:prepared",
@@ -182,23 +187,28 @@ describe("AgentHarness V2 compatibility adapter", () => {
182187"harness.run.completed",
183188]);
184189expect(diagnostics.events.every(({ metadata }) => metadata.trusted)).toBe(true);
185-expect(diagnostics.events[1]?.event).toMatchObject({
186-type: "harness.run.completed",
187-runId: "run-1",
188-sessionKey: "session-key",
189-sessionId: "session-1",
190-provider: "codex",
191-model: "gpt-5.4",
192-channel: "qa",
193-trigger: "manual",
194-harnessId: "codex",
195-pluginId: "codex-plugin",
196-outcome: "completed",
197-resultClassification: "reasoning-only",
198-yieldDetected: true,
199-itemLifecycle: { startedCount: 3, completedCount: 2, activeCount: 1 },
200-durationMs: expect.any(Number),
190+const completedEvent = diagnostics.events[1]?.event as
191+| (DiagnosticEventPayload & Record<string, unknown>)
192+| undefined;
193+expect(completedEvent?.type).toBe("harness.run.completed");
194+expect(completedEvent?.runId).toBe("run-1");
195+expect(completedEvent?.sessionKey).toBe("session-key");
196+expect(completedEvent?.sessionId).toBe("session-1");
197+expect(completedEvent?.provider).toBe("codex");
198+expect(completedEvent?.model).toBe("gpt-5.4");
199+expect(completedEvent?.channel).toBe("qa");
200+expect(completedEvent?.trigger).toBe("manual");
201+expect(completedEvent?.harnessId).toBe("codex");
202+expect(completedEvent?.pluginId).toBe("codex-plugin");
203+expect(completedEvent?.outcome).toBe("completed");
204+expect(completedEvent?.resultClassification).toBe("reasoning-only");
205+expect(completedEvent?.yieldDetected).toBe(true);
206+expect(completedEvent?.itemLifecycle).toEqual({
207+startedCount: 3,
208+completedCount: 2,
209+activeCount: 1,
201210});
211+expect(typeof completedEvent?.durationMs).toBe("number");
202212});
203213204214it("emits trusted harness error diagnostics with the failing lifecycle phase", async () => {
@@ -239,14 +249,15 @@ describe("AgentHarness V2 compatibility adapter", () => {
239249"harness.run.error",
240250]);
241251expect(diagnostics.events.every(({ metadata }) => metadata.trusted)).toBe(true);
242-expect(diagnostics.events[1]?.event).toMatchObject({
243-type: "harness.run.error",
244-phase: "send",
245-errorCategory: "Error",
246-cleanupFailed: true,
247-harnessId: "codex",
248-durationMs: expect.any(Number),
249-});
252+const errorEvent = diagnostics.events[1]?.event as
253+| (DiagnosticEventPayload & Record<string, unknown>)
254+| undefined;
255+expect(errorEvent?.type).toBe("harness.run.error");
256+expect(errorEvent?.phase).toBe("send");
257+expect(errorEvent?.errorCategory).toBe("Error");
258+expect(errorEvent?.cleanupFailed).toBe(true);
259+expect(errorEvent?.harnessId).toBe("codex");
260+expect(typeof errorEvent?.durationMs).toBe("number");
250261});
251262252263it("runs cleanup with the original failure and preserves that failure", async () => {
@@ -276,13 +287,14 @@ describe("AgentHarness V2 compatibility adapter", () => {
276287await expect(runAgentHarnessV2LifecycleAttempt(harness, params)).rejects.toThrow(
277288"codex app-server send failed",
278289);
279-expect(cleanup).toHaveBeenCalledWith(
280-expect.objectContaining({
281-error: sendError,
282-prepared: expect.objectContaining({ lifecycleState: "prepared" }),
283-session: expect.objectContaining({ lifecycleState: "started" }),
284-}),
285-);
290+const cleanupInput = mockCallArg<{
291+error?: unknown;
292+prepared?: { lifecycleState?: string };
293+session?: { lifecycleState?: string };
294+}>(cleanup);
295+expect(cleanupInput.error).toBe(sendError);
296+expect(cleanupInput.prepared?.lifecycleState).toBe("prepared");
297+expect(cleanupInput.session?.lifecycleState).toBe("started");
286298});
287299288300it("runs cleanup for failed prepare/start lifecycle stages", async () => {
@@ -310,11 +322,14 @@ describe("AgentHarness V2 compatibility adapter", () => {
310322await expect(runAgentHarnessV2LifecycleAttempt(harness, params)).rejects.toThrow(
311323"codex app-server start failed",
312324);
313-expect(cleanup).toHaveBeenCalledWith({
314-error: startError,
315-prepared: expect.objectContaining({ lifecycleState: "prepared" }),
316-session: undefined,
317-});
325+const cleanupInput = mockCallArg<{
326+error?: unknown;
327+prepared?: { lifecycleState?: string };
328+session?: unknown;
329+}>(cleanup);
330+expect(cleanupInput.error).toBe(startError);
331+expect(cleanupInput.prepared?.lifecycleState).toBe("prepared");
332+expect(cleanupInput.session).toBeUndefined();
318333});
319334320335it("passes raw send results to cleanup when outcome resolution fails", async () => {
@@ -343,14 +358,16 @@ describe("AgentHarness V2 compatibility adapter", () => {
343358await expect(runAgentHarnessV2LifecycleAttempt(harness, params)).rejects.toThrow(
344359"outcome classification failed",
345360);
346-expect(cleanup).toHaveBeenCalledWith(
347-expect.objectContaining({
348-error: outcomeError,
349-result: rawResult,
350-prepared: expect.objectContaining({ lifecycleState: "prepared" }),
351-session: expect.objectContaining({ lifecycleState: "started" }),
352-}),
353-);
361+const cleanupInput = mockCallArg<{
362+error?: unknown;
363+result?: unknown;
364+prepared?: { lifecycleState?: string };
365+session?: { lifecycleState?: string };
366+}>(cleanup);
367+expect(cleanupInput.error).toBe(outcomeError);
368+expect(cleanupInput.result).toBe(rawResult);
369+expect(cleanupInput.prepared?.lifecycleState).toBe("prepared");
370+expect(cleanupInput.session?.lifecycleState).toBe("started");
354371});
355372356373it("surfaces cleanup failures after successful outcomes", async () => {
@@ -397,13 +414,11 @@ describe("AgentHarness V2 compatibility adapter", () => {
397414expect(v2.resume).toBeUndefined();
398415expect(await v2.send(session)).toBe(result);
399416expect(runAttempt).toHaveBeenCalledWith(params);
400-expect(session).toMatchObject({
401-harnessId: "codex",
402-label: "Codex",
403-pluginId: "codex-plugin",
404- params,
405-lifecycleState: "started",
406-});
417+expect(session.harnessId).toBe("codex");
418+expect(session.label).toBe("Codex");
419+expect(session.pluginId).toBe("codex-plugin");
420+expect(session.params).toBe(params);
421+expect(session.lifecycleState).toBe("started");
407422expect(prepared.lifecycleState).toBe("prepared");
408423});
409424@@ -422,10 +437,9 @@ describe("AgentHarness V2 compatibility adapter", () => {
422437const v2 = adaptAgentHarnessToV2(harness);
423438const session = await v2.start(await v2.prepare(params));
424439425-expect(await v2.resolveOutcome(session, result)).toMatchObject({
426-agentHarnessId: "codex",
427-agentHarnessResultClassification: "empty",
428-});
440+const outcome = await v2.resolveOutcome(session, result);
441+expect(outcome.agentHarnessId).toBe("codex");
442+expect(outcome.agentHarnessResultClassification).toBe("empty");
429443expect(harness.classify).toHaveBeenCalledWith(result, params);
430444});
431445@@ -445,10 +459,9 @@ describe("AgentHarness V2 compatibility adapter", () => {
445459const v2 = adaptAgentHarnessToV2(harness);
446460const session = await v2.start(await v2.prepare(params));
447461448-expect(await v2.resolveOutcome(session, result)).toMatchObject({
449-agentHarnessId: "codex",
450-agentHarnessResultClassification: "reasoning-only",
451-});
462+const outcome = await v2.resolveOutcome(session, result);
463+expect(outcome.agentHarnessId).toBe("codex");
464+expect(outcome.agentHarnessResultClassification).toBe("reasoning-only");
452465});
453466454467it("clears stale non-ok classification when classification resolves to ok", async () => {
@@ -470,7 +483,7 @@ describe("AgentHarness V2 compatibility adapter", () => {
470483const session = await v2.start(await v2.prepare(params));
471484472485const classified = await v2.resolveOutcome(session, result);
473-expect(classified).toMatchObject({ agentHarnessId: "codex" });
486+expect(classified.agentHarnessId).toBe("codex");
474487expect(classified).not.toHaveProperty("agentHarnessResultClassification");
475488});
476489@@ -516,9 +529,7 @@ describe("AgentHarness V2 compatibility adapter", () => {
516529sessionFile: "/tmp/session.jsonl",
517530workspaceDir: "/tmp/workspace",
518531}),
519-).resolves.toMatchObject({
520-compacted: true,
521-});
532+).resolves.toHaveProperty("compacted", true);
522533await v2.reset?.({ reason: "reset" });
523534await v2.dispose?.();
524535此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。