fix(rectification): show spoken collect questions in the chat UI
Independent Staging Quality Gate / validate (push) Successful in 10m32s
Independent Staging Quality Gate / publish (push) Successful in 8m46s

Spoken collect prompts lived only in GET current_question. The chat never
parsed that field, Agent projections returned null after evidence writes,
and active_focus followups collapsed the questionId. Render the parsed
prompt, keep choiceReady on real cards, and give collect focuses a stable
domain-scoped id.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-30 00:51:14 +08:00
co-authored by Cursor
parent 3a0319694e
commit f5c02924c9
13 changed files with 452 additions and 15 deletions
@@ -32,7 +32,7 @@ import {
shouldDeclineCollectFocus,
shouldContinueAgentForDatedEvent,
} from "@/lib/rectification-agentic/v9/turn-intent-classifier";
import { persistServerOwnedFocus, openQuestionFromPersistedFocus, isCollectFocusSchema } from "@/lib/rectification-agentic/v9/server-focus";
import { persistServerOwnedFocus, openQuestionFromPersistedFocus, isCollectFocusSchema, isRenderableChoiceOpenQuestion } from "@/lib/rectification-agentic/v9/server-focus";
import { buildMethodFollowupPlan } from "@/lib/rectification-agentic/v9/method-followup";
export const runtime = "nodejs";
@@ -451,7 +451,7 @@ export async function POST(request: Request) {
followup: plan.next_followup,
});
const open = openQuestionFromPersistedFocus(persisted);
if (open && persisted.focus && open.unrenderable !== true) {
if (open && persisted.focus && isRenderableChoiceOpenQuestion(open)) {
let classified = null;
try {
classified = await classifyRectificationTurnIntent(selectedModel, {