
























@@ -0,0 +1,140 @@
1+import { describe, expect, it } from "vitest";
2+import {
3+evaluateMattermostNoVisibleReply,
4+formatMattermostNoVisibleReplyLog,
5+} from "./no-visible-reply-diagnostic.js";
6+7+describe("evaluateMattermostNoVisibleReply", () => {
8+it("flags substantive text payloads that delivered empty (regression: #80501)", () => {
9+const violation = evaluateMattermostNoVisibleReply({
10+outcome: "empty",
11+payload: { text: "Here is the result of the work I did..." },
12+});
13+expect(violation).toStrictEqual({
14+reason: "no-visible-reply-after-final-delivery",
15+outcome: "empty",
16+finalTextLength: "Here is the result of the work I did...".length,
17+mediaUrlCount: 0,
18+});
19+});
20+21+it("flags payloads with media URLs that delivered empty (regression: #80501)", () => {
22+const violation = evaluateMattermostNoVisibleReply({
23+outcome: "empty",
24+payload: { mediaUrl: "https://example.org/a.png" },
25+});
26+expect(violation).toStrictEqual({
27+reason: "no-visible-reply-after-final-delivery",
28+outcome: "empty",
29+finalTextLength: 0,
30+mediaUrlCount: 1,
31+});
32+});
33+34+it("counts entries from mediaUrls[] alongside the singular mediaUrl", () => {
35+const violation = evaluateMattermostNoVisibleReply({
36+outcome: "empty",
37+payload: {
38+mediaUrl: "https://example.org/a.png",
39+mediaUrls: ["https://example.org/b.png", "https://example.org/c.png"],
40+},
41+});
42+expect(violation?.mediaUrlCount).toBe(3);
43+});
44+45+it("does not flag reasoning_skipped outcome (intentional suppression)", () => {
46+expect(
47+evaluateMattermostNoVisibleReply({
48+outcome: "reasoning_skipped",
49+payload: { text: "Reasoning: hidden" },
50+}),
51+).toBeNull();
52+});
53+54+it("does not flag text outcome (visible delivery happened)", () => {
55+expect(
56+evaluateMattermostNoVisibleReply({
57+outcome: "text",
58+payload: { text: "hello" },
59+}),
60+).toBeNull();
61+});
62+63+it("does not flag media outcome (visible delivery happened)", () => {
64+expect(
65+evaluateMattermostNoVisibleReply({
66+outcome: "media",
67+payload: { mediaUrl: "https://example.org/a.png" },
68+}),
69+).toBeNull();
70+});
71+72+it("does not flag empty outcome when the payload was nominally empty (no text or media at all)", () => {
73+expect(
74+evaluateMattermostNoVisibleReply({
75+outcome: "empty",
76+payload: {},
77+}),
78+).toBeNull();
79+expect(
80+evaluateMattermostNoVisibleReply({
81+outcome: "empty",
82+payload: { text: "" },
83+}),
84+).toBeNull();
85+expect(
86+evaluateMattermostNoVisibleReply({
87+outcome: "empty",
88+payload: { text: " \n\t " },
89+}),
90+).toBeNull();
91+});
92+93+it("trims whitespace when measuring finalTextLength", () => {
94+const violation = evaluateMattermostNoVisibleReply({
95+outcome: "empty",
96+payload: { text: " hello " },
97+});
98+expect(violation?.finalTextLength).toBe("hello".length);
99+});
100+});
101+102+describe("formatMattermostNoVisibleReplyLog", () => {
103+it("emits a grep-friendly single-line diagnostic with the expected key/value pairs", () => {
104+const line = formatMattermostNoVisibleReplyLog({
105+violation: {
106+reason: "no-visible-reply-after-final-delivery",
107+outcome: "empty",
108+finalTextLength: 137,
109+mediaUrlCount: 0,
110+},
111+to: "channel:town-square",
112+accountId: "default",
113+agentId: "main",
114+});
115+expect(line).toBe(
116+"mattermost no-visible-reply: no-visible-reply-after-final-delivery" +
117+" to=channel:town-square" +
118+" accountId=default" +
119+" agentId=main" +
120+" outcome=empty" +
121+" finalTextLength=137" +
122+" mediaUrlCount=0",
123+);
124+});
125+126+it("falls back to unknown when agentId is undefined", () => {
127+const line = formatMattermostNoVisibleReplyLog({
128+violation: {
129+reason: "no-visible-reply-after-final-delivery",
130+outcome: "empty",
131+finalTextLength: 1,
132+mediaUrlCount: 0,
133+},
134+to: "channel:x",
135+accountId: "y",
136+agentId: undefined,
137+});
138+expect(line).toContain("agentId=unknown");
139+});
140+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。