

























@@ -1,11 +1,14 @@
11import { describe, expect, it } from "vitest";
22import {
33buildQaAgenticParityComparison,
4+buildQaRuntimeParityReport,
45computeQaAgenticParityMetrics,
56QaParityLabelMismatchError,
67renderQaAgenticParityMarkdownReport,
8+renderQaRuntimeParityMarkdownReport,
79type QaParityReportScenario,
810type QaParitySuiteSummary,
11+type QaRuntimeParitySuiteSummary,
912} from "./agentic-parity-report.js";
10131114const FULL_PARITY_PASS_SCENARIOS: QaParityReportScenario[] = [
@@ -29,6 +32,82 @@ function withScenarioOverride(name: string, override: Partial<QaParityReportScen
2932);
3033}
313435+function makeRuntimeParitySummary(): QaRuntimeParitySuiteSummary {
36+return {
37+scenarios: [
38+{
39+name: "Approval turn tool followthrough",
40+status: "pass",
41+steps: [],
42+runtimeParity: {
43+scenarioId: "approval-turn-tool-followthrough",
44+drift: "none",
45+cells: {
46+pi: {
47+runtime: "pi",
48+transcriptBytes: '{"role":"assistant"}\n',
49+toolCalls: [{ tool: "read_file", argsHash: "a", resultHash: "r" }],
50+finalText: "done",
51+usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
52+wallClockMs: 20,
53+bootStateLines: [],
54+},
55+codex: {
56+runtime: "codex",
57+transcriptBytes: '{"role":"assistant"}\n',
58+toolCalls: [{ tool: "read_file", argsHash: "a", resultHash: "r" }],
59+finalText: "done",
60+usage: { inputTokens: 8, outputTokens: 4, totalTokens: 12 },
61+wallClockMs: 18,
62+bootStateLines: [],
63+},
64+},
65+},
66+},
67+{
68+name: "Compaction retry after mutating tool",
69+status: "fail",
70+steps: [],
71+runtimeParity: {
72+scenarioId: "compaction-retry-after-mutating-tool",
73+drift: "tool-call-shape",
74+driftDetails: "tool call 1 differs",
75+cells: {
76+pi: {
77+runtime: "pi",
78+transcriptBytes: '{"role":"assistant"}\n',
79+toolCalls: [{ tool: "read_file", argsHash: "a", resultHash: "r" }],
80+finalText: "done",
81+usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
82+wallClockMs: 20,
83+bootStateLines: [],
84+},
85+codex: {
86+runtime: "codex",
87+transcriptBytes: '{"role":"assistant"}\n',
88+toolCalls: [{ tool: "read_file", argsHash: "b", resultHash: "r" }],
89+finalText: "done",
90+usage: { inputTokens: 9, outputTokens: 4, totalTokens: 13 },
91+wallClockMs: 19,
92+bootStateLines: [],
93+},
94+},
95+},
96+},
97+],
98+counts: {
99+total: 2,
100+passed: 1,
101+failed: 1,
102+},
103+run: {
104+providerMode: "mock-openai",
105+primaryModel: "openai/gpt-5.5",
106+runtimePair: ["pi", "codex"],
107+},
108+};
109+}
110+32111describe("qa agentic parity report", () => {
33112it("computes first-wave parity metrics from suite summaries", () => {
34113const summary: QaParitySuiteSummary = {
@@ -714,4 +793,33 @@ status=done`,
714793"# OpenClaw Agentic Parity Report — openai/gpt-5.5-alt vs openai/gpt-5.5",
715794);
716795});
796+797+it("builds a runtime parity report from suite summaries", () => {
798+const report = buildQaRuntimeParityReport({
799+summary: makeRuntimeParitySummary(),
800+comparedAt: "2026-05-10T00:00:00.000Z",
801+});
802+803+expect(report.runtimePair).toEqual(["pi", "codex"]);
804+expect(report.pass).toBe(false);
805+expect(report.driftCounts.none).toBe(1);
806+expect(report.driftCounts["tool-call-shape"]).toBe(1);
807+expect(report.failures).toContain(
808+"Compaction retry after mutating tool drift=tool-call-shape (tool call 1 differs).",
809+);
810+});
811+812+it("renders a readable runtime parity markdown report", () => {
813+const report = renderQaRuntimeParityMarkdownReport(
814+buildQaRuntimeParityReport({
815+summary: makeRuntimeParitySummary(),
816+comparedAt: "2026-05-10T00:00:00.000Z",
817+}),
818+);
819+820+expect(report).toContain("# OpenClaw Runtime Parity Report — pi vs codex");
821+expect(report).toContain("| Tool-call-shape drift | 1 |");
822+expect(report).toContain("### Compaction retry after mutating tool");
823+expect(report).toContain("- drift: tool-call-shape");
824+});
717825});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。