feat(rectification): the server writes the evidence recap — 「记下了 N 件事」 with the ledger list collapsed under it (BUG-1136)

- Evidence turns whose batch accepted items: the body is the server recap
  built from those items (two or fewer listed inline, more as a count);
  the model no longer restates them (both prompt sets updated).
- The case snapshot carries each assistant turn's recorded evidence from
  the ledger (rejected/superseded excluded); the message shows it in a
  collapsed <details> list when more than two.
- Chinese date labels read straight into the event phrase (2016年入学);
  ISO labels keep their space.
- Assertions updated with original/new/reason notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-10-01 10:40:29 +08:00
co-authored by Claude Opus 5.5
parent 408b22749e
commit 9d302e515c
21 changed files with 244 additions and 27 deletions
@@ -45,6 +45,8 @@ export type RenderMessage = ChatMessageView & {
question?: TurnQuestion;
candidateOffer?: Readonly<{ resultId: string }>;
segmentConsistency?: SegmentSummary;
/** BUG-1136: what this evidence turn recorded, from the ledger. */
recordedEvidence?: readonly string[];
};
export type RectificationMessageActions = Readonly<{
@@ -167,7 +169,20 @@ function RectificationMessageEntryView({
&& (questionIsDeadUnanswered(question)
|| (currentQuestionFocusId !== null && currentQuestionFocusId !== question.focus_id)),
);
const afterAnswer = question && displayedMessage.state === "settled" && !replacedQuestion
// BUG-1136 (D2): more than two recorded items read as 「记下了 N 件事」 in
// the body; the items themselves (ledger lines) sit here, collapsed.
const recorded = settled && (message.recordedEvidence?.length ?? 0) > 2
? message.recordedEvidence!
: null;
const recordedList = recorded ? (
<details className="rectification-recorded-evidence">
<summary>{`看记下的 ${recorded.length} 件`}</summary>
<ul>
{recorded.map((line, index) => <li key={`${index}:${line}`}>{line}</li>)}
</ul>
</details>
) : null;
const questionBlock = question && displayedMessage.state === "settled" && !replacedQuestion
? (
<div className="rectification-message-question">
<p className="rectification-message-question__prompt">{question.prompt}</p>
@@ -190,6 +205,9 @@ function RectificationMessageEntryView({
)}
</div>
)
: null;
const afterAnswer = recordedList || questionBlock
? <>{recordedList}{questionBlock}</>
: undefined;
return (