Commit Graph
114 Commits
Author SHA1 Message Date
Jesse_ChenandClaude Opus 5 ca0204984b feat(rectification): 区间常驻条补代表分钟与已答题数,盘面五段折叠收成两段
Independent Staging Quality Gate / validate (push) Canceled after 3m14s
Independent Staging Quality Gate / publish (push) Canceled after 0s
R7 / 决策 D10。任务书 docs/tasks/TASK-cend-surfaces-claude-alignment-20260916.md。

T7.1 常驻条。任务书 E9 说区间只在盘面标题行,实际读代码:对话区顶部
已有常驻条 RectificationTimeline 且已显示区间与宽度,窄屏 .is-compact 下
也可见。真正只存在于 .rectification-board__clock 的是代表分钟——窄屏盘面
是默认关闭的 overlay,代表分钟就此看不见。所以没有另造第二条(会撞固定条
高这条正确性约束),而是在既有条上补齐缺的两项:

  05:07–05:09 · 3 分钟 · 代表分钟 05:08 · 已答 6 题

代表分钟与盘面标题行是同一次 workingRectificationTime(result) 调用,一个
值两处用,不是两条推导路径。已答题数逐字读服务端的
inference_state.answered_probe_count,投影没给就整项不显示,不补「已答 0 题」。
条上不写确认,边界句仍只在交付/采用旁白里出现一次。读数只增宽不增高:条高
在滚动容器外,变高会让贴底读者的内容无声滑出视野。

收窄进度未做,触发让步顺序第 5 条。没有这个字段(服务端只把这句话拼进旁白
正文),且前端自己减会算错——candidate_range 是当前窗口且会放宽(BUG-572),
拿它当「最初」相减会把一次放宽报成一次收窄。缺口与解除条件写进 BLOCKED.md。

T7.2 盘面折叠。实际有 8 个 details(任务书记的五处漏了交界节奏、错标了两块),
按内容归成「候选分钟」(换升时刻 + 次级候选)与「参数与口径」(宫位表、确认门、
本轮技法、两段本命上升、经历与大运对照含双轨一致性、交界节奏)。每块保留原有
渲染条件,engineMeaningToDisplayCopy() 仍是 5 处,逐分钟行的 is-changed /
当前时间 一字未改。共享组件 technique-audit-disclosure.tsx 未动。

顺带修掉一个静默失效的断言:rectification-agentic-entry 用
board.slice(indexOf(A), indexOf(B)),B 改名后 indexOf 返回 -1,slice(i, -1)
会悄悄退化成几乎整份文件,底下四条 doesNotMatch 照样绿。已换成带越界断言的
sliceBetween()。两处改动的断言都在测试里写了原值/新值/原因。

tsc 0 错;lint 0 error / 118 warning(同基线);npm test 3350 → 3360,失败
仍是 31 条无 Docker 用例且与基线逐条一致;next build exit 0,/ 仍 ○ Static;
产物 CSS gzip 39,017 → 38,973 B(−0.11%)。

窄屏 .is-compact 下常驻条的实际可见性无 Chrome 无法验证,已按任务书写成环境
缺口,未标通过;CSS 上已确认无任何规则在该状态下隐藏该条,并写成测试断言。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
2026-09-16 06:44:49 +00:00
Jesse_ChenandClaude Opus 5 66d9f59d84 feat(ui): 标题不再落宋体,强调色分阶换 coral,删输入框常驻底栏(BUG-737/738)
Independent Staging Quality Gate / validate (push) Failing after 9m26s
Independent Staging Quality Gate / publish (push) Skipped
BUG-737:--font-display 以两个从未加载的 Anthropic 授权字体开头
(Tiempos Headline / StyreneB:无 @font-face、public/ 无字体、layout.tsx
只 vendor 了 Inter),于是每个中文标题都掉到 Songti SC / SimSun——20 条
规则宽,含助手回答正文的 h2/h3。display 与 body 合并为同一条无衬线栈,
层级改由字重承担(33 条 display 规则 400→500)。

拉丁衬线方案实测否决:Newsreader 拉丁子集 132 KB(Inter 的 2.7 倍),
只为给一个品牌字上衬线,且会把「D10 事业盘怎么读」劈成两种字形。

BUG-738:亮色 #85432f 与暗色 #d78064 不同源;--color-ring 在
@theme inline 里硬编码不跟随 :root。产品拍板换 Claude coral #cc785c,
但实测它作文字色只有 3.14:1,而 62 个调用点里 53 个是 color:。
按角色拆两阶:--color-action #a9583e(文字 4.85:1)、
--color-action-strong #cc785c(填充/导轨/焦点环,3:1 非文字阈值)。
--report-accent 刻意保持 #85432f(报告是纸面,不跟应用强调色)。

T1.3/T1.4:模型选择器进 ChatComposer 的 toolbar 插槽,删掉常驻 44px 的
.composer-footer;顶栏 68→46px,「分析对象:」改为标题旁静默 chip。

防复发:新增 font-stack-loadable-contract,断言字体栈里每个 family 要么
vendored 要么是系统字体,且 --font-display 不得触达任何 CJK 衬线。

测试 3346→3350,fail 仍 31 且清单与基线逐条一致;/ 仍 Static;
CSS gzip 41,095→41,096(+0.002%);快速门 pytest 段 798 passed / 0 failed。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
2026-09-16 04:53:14 +00:00
jesse-ux 58ccafb67c fix(rectification): stop re-parsing settled messages on every stream frame
Independent Staging Quality Gate / validate (push) Failing after 6m18s
Independent Staging Quality Gate / publish (push) Skipped
2026-09-16 07:13:12 +08:00
jesse-ux f51e494c5a fix(chat): keep rectification sessions findable and keep the delivery card
Independent Staging Quality Gate / validate (push) Failing after 6m45s
Independent Staging Quality Gate / publish (push) Skipped
Rectification answers now advance chat_sessions.updated_at (BUG-704).
A ?c= id missing from the loaded page is fetched before anyone may call
it deleted (BUG-705). The range card no longer has a post-card tie-break
button; live questions leave the card visible with adopt locked
(BUG-706/708). Spoken copy bans 相对支持度 (BUG-709).

Task docs assigned 700-704; qizheng already took 700-703.
2026-09-15 17:10:53 +08:00
jesse-ux c5fbee56a6 fix(rectification): label declared birth time as record or estimate (BUG-690)
Independent Staging Quality Gate / validate (push) Failing after 8m55s
Independent Staging Quality Gate / publish (push) Skipped
Hospital records, family estimates and period-only windows now keep distinct copy on the board and range card. Scoring still uses the reported clock as the search-window centre. Hospital minutes outside the current range are stated with the offset and no preference.
2026-09-14 23:20:15 +08:00
jesse-ux 7f28bfecbb fix(rectification): ask tie-break questions before the range card (BUG-685/686/687)
Close leads hold delivery until unused D9/D10 style questions are asked. Tie-break POST merges the new turn into the transcript. Range copy no longer lists declined lines.
2026-09-14 18:23:54 +08:00
jesse-ux 9da42c99d2 fix(rectification): keep tied-first from delivering while probes remain (BUG-683/684)
Independent Staging Quality Gate / validate (push) Successful in 13m48s
Independent Staging Quality Gate / publish (push) Successful in 2m6s
tied_first is only terminal when there is no dated probe and targeted collect is exhausted. An unnarrowed opening window cannot announce adopt. Delivered dead choice cards take the delivered gap instead of the repair copy.
2026-09-14 17:06:51 +08:00
jesse-ux d5a8db0a4e fix(rectification): deliver range cards on tied first place instead of falling back to collect (BUG-680/681/682)
Independent Staging Quality Gate / validate (push) Successful in 17m18s
Independent Staging Quality Gate / publish (push) Successful in 13m52s
Refresh persist failures no longer count as attempts. tied_first completes with a range before stillNeedNarrowing. Delivery narration and cards share DELIVERY_OUTCOMES. The question gap gets a delivered terminal so the unavailable copy does not appear after a range is given.
2026-09-14 15:41:04 +08:00
jesse-ux 69ffa07d6b fix(rectification): stop speaking unstampable distinguish stems (BUG-674/675)
Independent Staging Quality Gate / validate (push) Failing after 20s
Independent Staging Quality Gate / publish (push) Skipped
Distinguish followups that cannot stamp a probe now go to persistExhaustionCollect instead of repeating the card stem in the assistant body. Choice focuses without asked_turn_id hang on the last assistant turn, and persisted_question with a live choice_card renders the existing card. Representative-time inconsistency is warn-only (BUG-676 investigating).
2026-09-14 03:42:48 +08:00
jesse-ux 8221c6121b fix(rectification): restore targeted collect cards from spoken focus (BUG-673)
Independent Staging Quality Gate / validate (push) Successful in 10m39s
Independent Staging Quality Gate / publish (push) Successful in 2m9s
Keep targeted existence questions as A-D cards. Recover collect-schema
stock by question-id prefix, surface the stem when persist fails, and
send spoken targeted existence to the repair exit instead of a naked prompt.
2026-09-14 01:51:55 +08:00
Jesse_ChenandCursor 9912760104 fix(rectification): keep range-card tie-break entry honest after D9/D10 answers (BUG-666~668)
Independent Staging Quality Gate / validate (push) Successful in 13m8s
Independent Staging Quality Gate / publish (push) Canceled after 9m59s
Hide the button once both personality cards are answered, persist the second card in the same opt-in round, and freeze Skill 10.0.26.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 22:45:31 +08:00
Jesse_ChenandCursor 192845ce2f fix(rectification): keep targeted collect cards tappable after snapshot reread (BUG-669~671)
Independent Staging Quality Gate / validate (push) Successful in 25m6s
Independent Staging Quality Gate / publish (push) Successful in 2m9s
GET dropped the A–D card when the recast had no choice_frame, so a refresh left a disabled card and a collect-wait. Project from the persisted copy, rebuild the keep frame, and send a dead choice to repair-exit.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 21:50:35 +08:00
Jesse_ChenandCursor 530f260f76 fix(rectification): ask remaining split lines one card at a time (BUG-661~663)
Independent Staging Quality Gate / validate (push) Successful in 12m9s
Independent Staging Quality Gate / publish (push) Successful in 2m17s
Dated-pool empty now yields existence cards per remaining layer, leftover-candidate copy, and an optional D9/D10 tie-break on the range card. Skill 10.0.25.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 16:50:25 +08:00
Jesse_ChenandCursor dd8f35f7ba fix(rectification): invite-first collect, holdout at 4 events, Skill 10.0.23 (BUG-646–648)
Stop domain-wheel collecting and age-band years in prompts. Ask until the training gate, then discriminate until convergence, then deliver a range plus a concrete follow-up. Reserve holdout only with four dated events.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-11 01:43:02 +08:00
Jesse_ChenandCursor a998b6ec53 fix(rectification): stop unwritten-evidence claims and same-cluster dasha false conflicts (BUG-635–640)
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
Host only says 记下了 after a real write; Mastra schema rejections fail closed. Ledger year keys no longer drop quality probes, dual-dasha agreement is per cluster, width uses cluster span, and public house tables follow the inference minute.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 17:38:37 +08:00
Jesse_ChenandCursor d96b24c276 fix(rectification): keep skipped health out of holdout and repair empty exits (BUG-626, BUG-627)
Independent Staging Quality Gate / validate (push) Successful in 12m11s
Independent Staging Quality Gate / publish (push) Successful in 7m54s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 11:59:47 +08:00
Jesse_ChenandCursor 0263658477 fix(rectification): host-fallback empty evidence turns and choice range narration (BUG-633, BUG-634)
Evidence turns that already recorded a batch no longer fail the whole run when the model emits no text; unchanged ranges now name which clock spans lead or lag, and the timeline no longer says 收窄.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 11:57:07 +08:00
Jesse_ChenandCursor f0ae8cc45b fix(rectification): drop 没有/记不清 collect chips (BUG-626)
Users consistently rejected skip chips on spoken collect. Typing those phrases still declines or skips the domain.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 22:20:35 +08:00
Jesse_ChenandCursor 15cede97e7 fix(rectification): keep the adopt-card lock in state so lint can pass (BUG-622)
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
Writing selectionOfferLockRef during render tripped react-hooks/refs after the two contract tests went green. The lock now updates like seededTurns, and nextSelectionCardLock reuses the same object when the key is unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 19:34:39 +08:00
Jesse_ChenandCursor ca921c3f2a fix(rectification): keep collect chips, timeline, and adopt cards aligned
Independent Staging Quality Gate / validate (push) Failing after 9m58s
Independent Staging Quality Gate / publish (push) Has been skipped
Move 没有/记不清 under the spoken question, inset the timeline to the assistant column, and keep the three-column card after 更像这个 with the closing line under it (BUG-618–620).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 18:10:02 +08:00
Jesse_ChenandCursor fa293b318d merge origin/staging: timeline width/hollow marks (BUG-602/603) with conversation economy (BUG-604–606)
Independent Staging Quality Gate / validate (push) Successful in 14m38s
Independent Staging Quality Gate / publish (push) Successful in 13m31s
Keep both changelog entries, BUG_HISTORY 602–606, and both task-board rows at 待验收. Auto-merged chat.tsx retains inferenceMarks and collect-reply buttons.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 14:51:02 +08:00
Jesse_ChenandCursor aa7ccb30b7 fix(rectification): open with batch collect, add skip/decline buttons, keep one spoken sentence (BUG-604, BUG-605, BUG-606)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 14:23:37 +08:00
Jesse_ChenandCursor 92e3d5e7a3 fix(rectification): count timeline width inclusively and keep eliminated minutes hollow (BUG-602, BUG-603)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 13:58:55 +08:00
Jesse_ChenandClaude Fable 5 ce91a0d23c feat(rectification): show the credible range as a persistent timeline
The range is the only quantity that expresses convergence, and it existed
only as a sentence in the transcript. The bar makes it permanent.

It is the chat grid's first row, outside the scroll container, so
scrollHeight is untouched and use-conversation-scroll-anchor needs no
change. Its height is fixed because nothing observes it: a growing bar
would alter clientHeight and let an anchored reader lose the tail.

The axis is the current search window, not the opening one, since
widening overruns the opening window. Marks are binary — in range or
excluded — because relative support between candidate minutes carries no
demonstrated minute-level discrimination (BUG-560, blocked).

Band and marks move by transform alone; globals.css bans width
transitions, and transform keeps the motion off the layout path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr
2026-09-09 04:23:05 +00:00
Jesse_ChenandCursor 7e3b6cdc7a fix(rectification): simplify delivery card and guard double turns (BUG-595, BUG-596)
Independent Staging Quality Gate / validate (push) Successful in 25m9s
Independent Staging Quality Gate / publish (push) Successful in 37m19s
Make the range card row-select, drop the composer 先这样 control and adopt status bar, keep delivery copy to three sentences with a folded verification report, and skip a second no-message agent run after a terminal delivery turn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-08 19:56:48 +08:00
Jesse_ChenandCursor df182c16d6 fix(rectification): replay answered probes after evidence rescore (BUG-587, BUG-588)
Independent Staging Quality Gate / validate (push) Successful in 10m56s
Independent Staging Quality Gate / publish (push) Successful in 9m1s
Carry answered probe defs into the new candidate set, replay them by minute, and announce range changes on evidence turns.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-08 10:38:51 +08:00
Jesse_ChenandCursor a00b069dcc fix(rectification): unblock range-card tsc and restore post-adopt windows (BUG-583)
Independent Staging Quality Gate / validate (push) Successful in 13m23s
Independent Staging Quality Gate / publish (push) Successful in 30m54s
Null-check the candidate result before reading resultId so next build can ship. Adopt reconnects prospective windows on the first verify turn, and dismissing the range card now shows the collect hint.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 20:22:24 +08:00
Jesse_ChenandCursor ab57d03f06 fix(rectification): persist stop scores and deliver a range card (BUG-581–582)
Independent Staging Quality Gate / validate (push) Successful in 14m1s
Independent Staging Quality Gate / publish (push) Failing after 19m46s
Stop/idle reuse the scored evidence path so existing answers stay on the range. Delivery uses one range card (Skill 10.0.15) instead of four minute cards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 19:22:01 +08:00
Jesse_ChenandCursor 1ded6bb0d4 fix(rectification): hide option hover impact and composer step strip (BUG-575)
Hovering A/B/C/D rewrote a leading/lagging time line and made the card flicker; the step-state sentence above the composer was instructional filler, not something the user needed to answer.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 14:07:49 +08:00
Jesse_ChenandCursor 814c924e4a fix(rectification): exhaustion exit, explain layer, range reading, unknown-time scan (BUG-565–568)
Independent Staging Quality Gate / validate (push) Successful in 9m20s
Independent Staging Quality Gate / publish (push) Successful in 6m51s
Keep askable cards after exhaustion, explain each probe, read the adopted credible range in reports and chat, and compare declared periods before the minute grid when the clock is unknown.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 09:10:37 +08:00
Jesse_ChenandCursor 150d7ef189 fix(web): exit rectification when the probe pool is exhausted (BUG-558)
Stop falling through to "say another event" after dated and occupation collect are done. Deliver an adopt path or a gate sentence, and add a spoken-collect stop control.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 23:03:11 +08:00
Jesse_ChenandCursor dc6598d7e4 fix(web): keep the settings dialog one size and move billing into it (BUG-554)
The four account panes now share a fixed frame, chart profiles open as list then detail, and membership lives in the homepage dialog instead of a separate page.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 18:29:51 +08:00
Jesse_ChenandCursor 055b7adca9 fix(web): keep composer enabled while generating and treat stop as neutral (BUG-551, BUG-552)
Enter now queues one follow-up instead of dropping it, and a rectification stop leaves the streamed reply with a grey notice instead of an error alert.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 13:08:43 +08:00
Jesse_ChenandCursor 329f8a2109 fix(rectification): pin the adopt card and drop casual adopt copy
Independent Staging Quality Gate / validate (push) Successful in 11m34s
Independent Staging Quality Gate / publish (push) Successful in 1m56s
The time card stayed under an earlier collect question, and the close said to just use a time for now. Keep the card on the delivery turn and present the analysis as this round's result.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-05 02:03:19 +08:00
Jesse_ChenandCursor d4627a5019 fix(rectification): dedupe post-adopt verify and skip this probe only
Independent Staging Quality Gate / validate (push) Successful in 14m31s
Independent Staging Quality Gate / publish (push) Successful in 1m59s
Adopted reverse-verify repeated already-asked collect stems, treated 「这题跳过」 as stopping the case, and promised holdout/OOS checks that never ran. Collect spoken stems no longer prefix a year.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-04 21:51:59 +08:00
Jesse_ChenandCursor 41f973f036 fix(rectification): bind collect-denial follow-up to the asked turn
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
Saying no to a spoken collect left the next stem only on current_question, so the preparing spinner never cleared. Persist the ack, link asked_turn_id, and emit run.completed with turnId (BUG-525).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-04 16:27:53 +08:00
Jesse_ChenandCursor cfa824994e fix(rectification): keep a live analyzing step and drop the range-stop exits
Independent Staging Quality Gate / validate (push) Successful in 9m26s
Independent Staging Quality Gate / publish (push) Successful in 1m57s
A completed tool left only checkmarks under 正在分析, so the run looked stuck. The composer and scoring-card 先这样 buttons were unused early exits.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-04 12:46:10 +08:00
Jesse_ChenandClaude Fable 5.1 3c33e59814 feat(rectification): confirm the tap on the choice card and show the declared minute on the empty board
The choice card now marks the tapped option with a check and 已选择 and,
while the tap is being recorded, carries the same live row shape as a
timeline step instead of only a wait cursor. Before any candidate exists
the board's clock shows the declared birth minute, its body says what
fills it later, and the column narrows to minmax(16rem, 18rem); the
compact peek reads "填报 HH:MM". No house table is invented for the
declared time — the Case API does not provide one.

BUG-508, BUG-509

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-03 07:07:31 +00:00
Jesse_ChenandClaude Fable 5.1 1e50007c50 fix(rectification): keep one live row from a tapped choice or an adopted candidate through the follow-up turn
After a choice was recorded the chat removed its "正在记录本次选择…" row,
dropped `busy`, and let an effect start the follow-up turn a frame later —
one blank frame, and the next card could flash before the turn hid it.
Adopting a candidate showed nothing but a greyed button. `send` now takes a
continuation that reuses an existing live row, the choice and adoption
flows await it in the same async chain, `busy` is held throughout, and
adoption puts "正在采用 HH:MM…" at the end of the transcript before the
round trip.

BUG-506

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-03 07:07:31 +00:00
Jesse_ChenandClaude Fable 5.1 360989ca2c fix(rectification): make every gap a live row with retries, give an empty Case a start, and say why a run stopped
The chat used to show "当前没有可回答的问题,正在等待服务端更新" / "当前问题暂时无法显示"
/ "题目加载失败,请刷新" as bare copy above the composer. The gap between a
settled turn and its next question is now a state: `preparing` renders the
same timeline live row the reply uses ("正在准备下一个问题…") and refetches the
Case on a 2s timer up to two retries; `unavailable` renders one line and a
44px reload button. A snapshot that never arrived at hydration is the same
gap. A resumed Case with no turns and no server-started opening shows
"这段校正还没有开始。" with one 开始提问 action. Stopping a run keeps what
streamed and says so instead of "暂时不可用"; the opening turn's live row
names what is happening; a 402 explains itself for 600ms before leaving.

BUG-505, BUG-507

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-03 07:07:31 +00:00
Jesse_ChenandClaude Fable 5.1 53017d4153 fix(rectification): reveal the surface once — hydrate the Case before the switch, never remount, static entry feedback
Opening a rectification Case used to switch sessions first and read the
turns afterwards, so the reader saw a plain transcript, then an empty
panel, then a remount when the turns arrived (and again after the first
turn settled, because the panel key carried a ready/loading suffix).
The surface hook now reads turns and snapshot in one Case request under
the home reveal budget and only then makes the session active; the
sidebar defers the switch the same way; a session selected at bootstrap
(deep link, refresh) is hydrated during the prepare phase so the reveal
shows the surface itself; the panel key is the session/Case binding only,
later turns fill an empty transcript as a prop update, and unmounting
aborts any stream or snapshot read. The homepage card and the sidebar row
say 正在打开 statically while the Case opens — no spinner after the reveal.

BUG-505

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-03 07:07:31 +00:00
Jesse_ChenandCursor e8c98c37cf fix(rectification): restore collect-phase exit and drop the consult handoff
Independent Staging Quality Gate / validate (push) Successful in 8m29s
Independent Staging Quality Gate / publish (push) Successful in 1m45s
Public can_adopt no longer starves the collect fallback, 改选 scrolls to
the offer, opening collect uses other, and probe_year stays on the
schema. The status bar no longer starts an empty consultation chat.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-03 10:41:36 +08:00
Jesse_ChenandCursor 35e5781e66 fix(rectification): gate collect-phase adopt cards and keep post-adopt verify answerable
Independent Staging Quality Gate / validate (push) Successful in 9m50s
Independent Staging Quality Gate / publish (push) Successful in 1m53s
Public can_adopt follows session_outcome; reverse_verify reuses the persisted question id; offer cards settle on the owning message with a status-bar handoff.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-03 09:29:34 +08:00
Jesse_ChenandCursor 8dfe457f21 fix(rectification): keep choice options and scoring on the server
Independent Staging Quality Gate / validate (push) Successful in 9m30s
Independent Staging Quality Gate / publish (push) Successful in 1m50s
Agent set-focus was writing or dropping choice schema, so probes never scored. Force server-owned options, fail closed when focus list RPC errors, and require the probe year in spokenPrompt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 20:47:16 +08:00
Jesse_ChenandCursor d94049769e fix(rectification): put each question inside the assistant message
Independent Staging Quality Gate / validate (push) Successful in 25m7s
Independent Staging Quality Gate / publish (push) Successful in 2m8s
Focuses now carry asked_turn_id so GET rebuilds stem and options on the
same turn. Agent writes spokenPrompt; the live question slot is gone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 19:55:20 +08:00
Jesse_ChenandCursor 33d55b3a54 fix(rectification): satisfy React compiler lint for collect stem attach
Independent Staging Quality Gate / validate (push) Successful in 9m21s
Independent Staging Quality Gate / publish (push) Successful in 1m49s
Move the current-question ref off render and persist the collect stem from snapshot/send callbacks so ESLint no longer fails the staging gate.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 17:05:29 +08:00
Jesse_ChenandCursor b1d4796d30 fix(rectification): restore showActivity source lock for the staging gate
Independent Staging Quality Gate / validate (push) Failing after 8m5s
Independent Staging Quality Gate / publish (push) Has been skipped
Keep collect text on bubbleMessage but pass displayedMessage.state so the entry contract matches again.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 16:49:31 +08:00
Jesse_ChenandCursor 42c6de142b fix(rectification): put the collect stem in the assistant bubble
Independent Staging Quality Gate / validate (push) Failing after 8m27s
Independent Staging Quality Gate / publish (push) Has been skipped
The live question slot still rendered the collect prompt below the action icons when the streamed body was only a greeting. Join the GET prompt into that bubble and stop drawing a sibling collect slot.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 16:30:26 +08:00
Jesse_ChenandCursor 39c30b5597 fix(rectification): persist the collect stem on the same assistant turn
Independent Staging Quality Gate / validate (push) Successful in 7m55s
Independent Staging Quality Gate / publish (push) Successful in 1m47s
The live question slot disappeared on refresh because it was never written to assistant_message. Attach the current collect_spoken prompt to that turn before finalize so chat history keeps it.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 16:06:50 +08:00
Jesse_ChenandCursor 661a0dab14 fix(rectification): stop the opening body from repeating the collect prompt
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
Persist the interview slot before the opening turn, keep the stem in the question slot, and hide that slot while a run is busy so the same ask does not appear twice.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 14:53:10 +08:00