fix(rectification): keep same-sentence dated events after structured answers
Independent Staging Quality Gate / validate (push) Successful in 13m7s
Independent Staging Quality Gate / publish (push) Successful in 29m19s

The choice and collect fast paths applied the answer then returned,
so a dated event in the same utterance never reached the evidence
ledger. Idle persist also prechecked follow-up with a hardcoded
collect_evidence outcome instead of the dossier decision.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-29 23:18:07 +08:00
co-authored by Cursor
parent 078c1cdc0d
commit 3a0319694e
8 changed files with 306 additions and 17 deletions
@@ -30,6 +30,7 @@ import {
classifyRectificationTurnIntent,
optionIdForAnswerClass,
shouldDeclineCollectFocus,
shouldContinueAgentForDatedEvent,
} from "@/lib/rectification-agentic/v9/turn-intent-classifier";
import { persistServerOwnedFocus, openQuestionFromPersistedFocus, isCollectFocusSchema } from "@/lib/rectification-agentic/v9/server-focus";
import { buildMethodFollowupPlan } from "@/lib/rectification-agentic/v9/method-followup";
@@ -348,6 +349,7 @@ export async function POST(request: Request) {
if (!optionId) {
return completedMessageResponse("当前问题已更新,请刷新后重新作答。", requestId, caseId);
}
const continueToAgent = shouldContinueAgentForDatedEvent(classified);
const previous = previousInferenceFromReceipt(dossier.latestResult?.decisionReceipt ?? null);
const applied = await applyRectificationChoice(accounting, {
userId,
@@ -363,8 +365,11 @@ export async function POST(request: Request) {
optionId,
expectedRevision: previous?.revision ?? 0,
userDisplay: parsed.data.message ?? null,
deferFollowup: continueToAgent,
});
return completedMessageResponse(applied.narration, requestId, caseId);
if (!continueToAgent) {
return completedMessageResponse(applied.narration, requestId, caseId);
}
}
if (classified.intent === "stop_rectification") {
const previous = previousInferenceFromReceipt(dossier.latestResult?.decisionReceipt ?? null);
@@ -399,17 +404,21 @@ export async function POST(request: Request) {
classified = null;
}
if (shouldDeclineCollectFocus(classified)) {
const continueToAgent = shouldContinueAgentForDatedEvent(classified);
const applied = await applyCollectFocusDenial(accounting, {
userId,
caseId,
focusId: focus.id,
deferFollowup: continueToAgent,
});
await persistV9DeterministicTurn(accounting, userId, caseId, {
requestId,
userMessage: parsed.data.message ?? null,
assistantMessage: applied.narration,
});
return completedMessageResponse(applied.narration, requestId, caseId);
if (!continueToAgent) {
await persistV9DeterministicTurn(accounting, userId, caseId, {
requestId,
userMessage: parsed.data.message ?? null,
assistantMessage: applied.narration,
});
return completedMessageResponse(applied.narration, requestId, caseId);
}
}
} else {
let birthDate: string | null = null;