fix(rectification): one stem per turn, one card per focus (BUG-1045/1046)

BUG-1045 (recurrence of BUG-585 via BUG-969): the snapshot merge now drops
the attached stem from the streamed "ack + stem" text with the same
stripQuestionSentences the GET route uses; server text unchanged.

BUG-1046: a failed choice submit (409 / network) or typed send withdraws
the local answered mark, remounts the card, re-reads the Case and shows
"这次没提交上,请再点一次。"; the persisted question hangs on the latest
settled assistant message with other copies of the same focus removed
(standalone block only when nothing can carry it); willContinue and the
send() settle merge unseen assistant turns (same gap as BUG-685).

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-09-26 10:49:25 +08:00
co-authored by Claude Opus 5.5
parent 07998972e0
commit e4c1c7a342
18 changed files with 906 additions and 18 deletions
+3 -2
View File
@@ -291,8 +291,9 @@ The birth-time rectification session is the consultation transcript plus a house
|---|---|---|
| `opening` | live row “正在读取你的出生资料,准备第一个问题…”, then tool labels | enabled (typing queues), stop visible |
| `empty` | “这段校正还没有开始。” and one primary action “开始提问” | enabled |
| `question-live` | the asking message carries the embedded card or the spoken stem. An active spoken or choice focus without `asked_turn_id` hangs on the last assistant message, same avatar column | enabled, placeholder points at the card |
| `question-gap`, persisted question | only when no assistant message can carry the prompt; a host question row (`data-testid="persisted-question"`) | enabled, placeholder “请回答上面的问题…” |
| `question-live` | the asking message carries the embedded card or the spoken stem. An active spoken or choice focus without `asked_turn_id` hangs on the last assistant message, same avatar column. A deterministic reply streams “ack + stem” so the stem is readable before the card arrives; once the snapshot attaches the card, the bubble drops that sentence on the live transcript as well as on refresh (BUG-1045) | enabled, placeholder points at the card |
| `question-gap`, persisted question | the snapshot's current question hangs on the latest settled assistant message (the client does this too, not only GET), and any other copy of the same `focus_id` comes off: one focus, one card (BUG-1046). The host question row (`data-testid="persisted-question"`) appears only when no assistant message can carry the prompt: there is none, or the latest one already carries a different question | enabled, placeholder “请回答上面的问题…” |
| `question-live`, after a failed tap | the tapped option is taken back (question active again, nothing selected), the card remounts tappable, the Case is re-read, and the error line is “这次没提交上,请再点一次。” — never a second copy of the card below (BUG-1046) | enabled |
| `question-gap`, retries left | one timeline live row “正在准备下一个问题…”, refetching on a 2s timer up to two retries | enabled |
| `question-gap`, retries spent | “没有拿到下一个问题。” and a 44px “接着问” | enabled |
| `question-gap`, collect waiting | no “没有拿到下一个问题”; the last assistant line already has the precise gap. Never while the latest assistant message still carries an unanswerable tap question — that is the repair exit below (BUG-917) | enabled, placeholder “再说一件带年月的事” |