fix(rectification): show the house table and hide the activity fold
Independent Staging Quality Gate / validate (push) Failing after 9m39s
Independent Staging Quality Gate / publish (push) Has been skipped

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-19 20:11:51 +08:00
co-authored by Cursor
parent 4c33329b0c
commit c8af18e90a
19 changed files with 438 additions and 100 deletions
@@ -231,7 +231,7 @@ test("Agentic rectification scrolls the conversation container as streamed messa
assert.doesNotMatch(chat, /conversationEnd|scrollIntoView/);
});
test("rectification activity separates live work from the receipt above the Agent message", () => {
test("rectification keeps receipts for the varga sentence and hides Activity from the user", () => {
const activityHelper = chat.slice(
chat.indexOf("function completedReceiptFromPersisted"),
chat.indexOf("export function RectificationAgenticChat"),
@@ -241,10 +241,14 @@ test("rectification activity separates live work from the receipt above the Agen
assert.match(activityHelper, /filter\(isPublicRectificationTool\)/);
assert.match(activityHelper, /receipt\.methods/);
assert.match(activityHelper, /filter\(isPublicRectificationMethod\)/);
assert.match(chat, /activeActivity\?: PublicActivity/);
assert.match(chat, /completedReceipt\?: CompletedActivityReceiptView/);
assert.match(chat, /showActivity=\{displayedMessage\.state === "thinking" \|\| Boolean\(displayedMessage\.activeActivity\)\}/);
assert.match(chat, /"rectification-read-case": "正在读取校正记录…"/);
assert.match(chat, /showActivity=\{displayedMessage\.state === "thinking"\}/);
assert.match(chat, /vargaSentenceFromMethods/);
assert.match(chat, /vargaSentence=\{vargaSentence\}/);
assert.match(chat, /RectificationHouseTableView/);
assert.doesNotMatch(chat, /activeActivity/);
assert.doesNotMatch(chat, /正在读取校正记录/);
assert.doesNotMatch(chat, /<CompletedActivityReceipt/);
assert.match(chat, /event\.type === "tool\.activity"/);
assert.match(chat, /event\.status === "started"/);
assert.match(chat, /event\.status === "completed"/);
@@ -254,26 +258,16 @@ test("rectification activity separates live work from the receipt above the Agen
chat.indexOf("{messages.map((message) => {"),
chat.indexOf("{candidateResult?.selectionAllowed"),
);
const receiptIndex = messageRender.indexOf("<CompletedActivityReceipt");
const replyIndex = messageRender.indexOf("<ChatMessageRow");
assert.ok(receiptIndex >= 0 && replyIndex >= 0);
assert.ok(receiptIndex < replyIndex);
const houseIndex = messageRender.indexOf("<RectificationHouseTableView");
assert.ok(replyIndex >= 0);
assert.ok(houseIndex > replyIndex);
assert.match(completedActivityReceipt, /<details className=/);
assert.doesNotMatch(completedActivityReceipt, /<details[^>]*\sopen/);
assert.match(completedActivityReceipt, /本轮完成 · \$\{stepLabels\.length\} 个步骤 · \$\{receipt\.methods\.length\} 项计算依据/);
assert.match(completedActivityReceipt, /执行步骤/);
assert.match(completedActivityReceipt, /计算依据/);
assert.doesNotMatch(completedActivityReceipt, /<button|className=.*pill|className=.*tag/);
for (const genericCopy of ["开始本轮执行", "正在加载专用方法", "专用方法已加载", "本轮做了什么"]) {
assert.doesNotMatch(chat, new RegExp(genericCopy));
}
const activityStyles = styles.slice(styles.indexOf(".rectification-message-wrap"));
assert.match(activityStyles, /\.rectification-activity-receipt \{[\s\S]*color:/);
assert.match(activityStyles, /\.rectification-activity-receipt summary:focus-visible/);
const receiptRule = activityStyles.match(/\.rectification-activity-receipt \{([^}]*)\}/)?.[1] ?? "";
assert.doesNotMatch(receiptRule, /background:/);
assert.doesNotMatch(receiptRule, /border:/);
});
test("completed Agent replies restore feedback, copy and safe in-place regeneration actions", () => {
@@ -290,11 +284,11 @@ test("completed Agent replies restore feedback, copy and safe in-place regenerat
chat.indexOf("{messages.map((message) => {"),
chat.indexOf("{candidateResult?.selectionAllowed"),
);
const receiptIndex = messageRender.indexOf("<CompletedActivityReceipt");
const replyIndex = messageRender.indexOf("<ChatMessageRow");
const actionsIndex = messageRender.indexOf("<ChatMessageActions");
assert.ok(receiptIndex >= 0 && replyIndex >= 0 && actionsIndex >= 0);
assert.ok(receiptIndex < replyIndex && replyIndex < actionsIndex);
assert.ok(replyIndex >= 0 && actionsIndex >= 0);
assert.ok(replyIndex < actionsIndex);
assert.doesNotMatch(messageRender, /<CompletedActivityReceipt/);
assert.doesNotMatch(chat, /send\("message",\s*(?:oldText|previousText)/);
assert.doesNotMatch(regenerateRoute, /consultation-billing|reserveConsultation|billing\./);
@@ -320,6 +314,8 @@ test("candidate state renders from the snapshot API and never from sentinels", (
assert.match(chat, /isRecommendedRectificationCandidate/);
assert.match(chat, /已采用/);
assert.match(chat, /正在采用…/);
assert.match(chat, /RectificationHouseTableView/);
assert.match(styles, /\.rectification-house-table \{/);
});
@@ -344,6 +340,8 @@ test("rectification Agent output stays natural and keeps tool execution silent",
assert.match(agent, /完成凭证完全由服务端公开 Activity\/receipt 展示/);
assert.match(agent, /禁止只说记下了、会话会保留、以后再继续/);
assert.match(agent, /暂时想不到了 \/ 没有更多 \/ 先这样/);
assert.match(agent, /on_user_stop/);
assert.match(agent, /分盘句和宫位表由界面展示/);
assert.match(skill, /不得叙述读取 Skill/);
assert.match(skill, /完整回复可以(?:是)?零(?:个)?问题/);
assert.match(skill, /同一用户可以保留多个可恢复 Case/);