修复 DirectProject 对话状态条时机与被挤扁、Markdown 代码块换行与围栏解析 #511

Merged
suzmii merged 4 commits from fix/recover-100ms into master 2026-09-24 17:36:39 +08:00
Member

本次 PR 覆盖 AGC DirectProject 对话区的一批问题(按反馈分四次追加),共 4 个提交。

1. 状态条读秒 1 秒一跳、样式退化

  • DirectTurnElapsed 改用对话侧共享时钟 useLiveNow(100ms):耗时文案不足一分钟保留一位小数,秒级 tick 会让小数位一秒才动一格。
  • 状态条收敛为单行(去掉旧面板遗留的 min-height: 78px / gap: 9px),状态点与扫光走 --platform-accent,标题提到 --platform-text-strong,耗时加等宽数字。
  • 删除两条永不命中的选择器(卡片在消息列表外,规则却写着 …message-list > …)与只服务已不存在的 <p> 的样式。

2. 窗口变矮时状态条被挤扁

状态条带 overflow: hidden,按 flex 规范该项自动最小尺寸归零,于是成了 .project-chat-conversation 这条 flex 列里唯一还能被压缩的项(实测 300px 高挤到 33px、240px 时 24px,文字被裁)。补 flex: 0 0 auto,压缩全部交给消息列表;同一选择器的两条规则合并成一条。

窗口高 900 560 420 360 300 260 220
卡片高(改前) 36 36 36 36 33 24
卡片高(改后) 36 36 36 36 36 36 36

3. 状态条要等第一个 token 才出现

卡片原先只认原生 turnRunning,而 turn.started 要等宿主的应答返回才 append(模型首 token 之前,实测约 10 秒),这段窗口里界面完全没有「正在处理」的交代。改为读 DirectProjectTurnStatus.displayBusy(本地命令在飞 ∪ 原生已确认在跑),并把计时起点放宽到最新一个未结束回合——awaiting-start 也有用户发送时间。这更正了 2026-09-22「卡片口径取保守」那条决策,理由与后续影响已写入 decision-log.md

4. 代码块不换行,把消息宽度拉宽

pre 与块内 code 分别写过 white-space,两处都补 whitespace-pre-wrap + break-words:窄面板里长行改为自动换行,不再顶出横向滚动条。

5. 围栏粘在正文行里导致代码块解析错位

模型常把 直接粘在上一行末尾(`…实现细节(game.js):js… }````),而 CommonMark 只认整行围栏:粘着的 退化成正文,于是正文被当成代码渲染、或代码块一直不闭合把后面所有内容一起吞掉。新增 `normalizeMarkdownFences`:把「围栏前是非空白字符、围栏到行尾只剩语言标识」的行拆开。整行围栏、缩进围栏、行内代码(单个反引号与 ``文本x``)、代码里出现的const s = "```";)以及引用块 / 列表项开头的合法围栏(> ```js- ```js)都不受影响。

review 收口

  • 围栏归一化原先会把行内代码 文本 ```x``` 的末尾那截拆开,凭空造出一个开场围栏、把后面的正文全变成代码;补「同一行出现第二段围栏串就跳过」判据 + 用例。
  • useDirectProjectTurnStatus 的注释仍在写「卡片只读 nativeRunning」,与现状相反,已更正。
  • decision-log.md 新增 2026-09-24 条:记录卡片口径翻转(更正 2026-09-22 那条),并处置那条里「若窗口期也显示卡片,running 在渲染层就没有消费者」的预言——投影三态仍有消费者(DirectProjectTurn 的否定式 / 肯定式判断、状态条的起点),故不压缩成布尔。

验证

  • 真实 Chromium(一次性 Vite 夹具):
    • 状态条 36px 单行,600ms 内读秒从 18.0秒 走到 18.6秒;900 → 220px 高度全程 36px、无裁剪;prefers-reduced-motion: reduce 下动画关闭。
    • 长代码行 horizontalOverflow: false(换行生效);粘住的开场 / 收场围栏都渲染成正确结构,围栏之后的文字回到正文。
  • 新增 / 更新的用例(逐条做过变异验证,去掉修复即红):directProjectProcessStatus.test.tsxChatMarkdownMessage.test.tsx(换行契约 + 五类围栏场景)、appSurface/chat-composer.suite.tsturn.started 未到时空窗里卡片已出现且已计时)、appSurface/project-development.suite.ts(卡片几何契约)。
  • npx vitest run apps/ai-game-creator-shell/tests:186 passed / 1 skipped,1860 passed / 14 skipped(当前 head 的 CI run 2902 conclusion=success);AGC tsc --noEmitnpm run check:encodingnpm run check:doc-indexgit diff --check 通过。
本次 PR 覆盖 AGC DirectProject 对话区的一批问题(按反馈分四次追加),共 4 个提交。 ## 1. 状态条读秒 1 秒一跳、样式退化 - `DirectTurnElapsed` 改用对话侧共享时钟 `useLiveNow`(100ms):耗时文案不足一分钟保留一位小数,秒级 tick 会让小数位一秒才动一格。 - 状态条收敛为单行(去掉旧面板遗留的 `min-height: 78px` / `gap: 9px`),状态点与扫光走 `--platform-accent`,标题提到 `--platform-text-strong`,耗时加等宽数字。 - 删除两条永不命中的选择器(卡片在消息列表外,规则却写着 `…message-list > …`)与只服务已不存在的 `<p>` 的样式。 ## 2. 窗口变矮时状态条被挤扁 状态条带 `overflow: hidden`,按 flex 规范该项自动最小尺寸归零,于是成了 `.project-chat-conversation` 这条 flex 列里唯一还能被压缩的项(实测 300px 高挤到 33px、240px 时 24px,文字被裁)。补 `flex: 0 0 auto`,压缩全部交给消息列表;同一选择器的两条规则合并成一条。 | 窗口高 | 900 | 560 | 420 | 360 | 300 | 260 | 220 | |---|---|---|---|---|---|---|---| | 卡片高(改前) | 36 | 36 | 36 | 36 | 33 | — | 24 | | 卡片高(改后) | 36 | 36 | 36 | 36 | 36 | 36 | 36 | ## 3. 状态条要等第一个 token 才出现 卡片原先只认原生 `turnRunning`,而 `turn.started` 要等宿主的应答返回才 append(模型首 token 之前,实测约 10 秒),这段窗口里界面完全没有「正在处理」的交代。改为读 `DirectProjectTurnStatus.displayBusy`(本地命令在飞 ∪ 原生已确认在跑),并把计时起点放宽到最新一个**未结束**回合——`awaiting-start` 也有用户发送时间。这更正了 2026-09-22「卡片口径取保守」那条决策,理由与后续影响已写入 `decision-log.md`。 ## 4. 代码块不换行,把消息宽度拉宽 `pre` 与块内 `code` 分别写过 `white-space`,两处都补 `whitespace-pre-wrap` + `break-words`:窄面板里长行改为自动换行,不再顶出横向滚动条。 ## 5. 围栏粘在正文行里导致代码块解析错位 模型常把 ``` 直接粘在上一行末尾(`…实现细节(game.js):```js`、`… }````),而 CommonMark 只认整行围栏:粘着的 ``` 退化成正文,于是正文被当成代码渲染、或代码块一直不闭合把后面所有内容一起吞掉。新增 `normalizeMarkdownFences`:把「围栏前是非空白字符、围栏到行尾只剩语言标识」的行拆开。整行围栏、缩进围栏、行内代码(单个反引号与 ``文本 ```x``` ``)、代码里出现的 ```(`const s = "```";`)以及引用块 / 列表项开头的合法围栏(`> ```js`、`- ```js`)都不受影响。 ## review 收口 - 围栏归一化原先会把行内代码 ``文本 ```x``` `` 的末尾那截拆开,凭空造出一个开场围栏、把后面的正文全变成代码;补「同一行出现第二段围栏串就跳过」判据 + 用例。 - `useDirectProjectTurnStatus` 的注释仍在写「卡片只读 `nativeRunning`」,与现状相反,已更正。 - `decision-log.md` 新增 2026-09-24 条:记录卡片口径翻转(更正 2026-09-22 那条),并处置那条里「若窗口期也显示卡片,`running` 在渲染层就没有消费者」的预言——投影三态仍有消费者(`DirectProjectTurn` 的否定式 / 肯定式判断、状态条的起点),故不压缩成布尔。 ## 验证 - 真实 Chromium(一次性 Vite 夹具): - 状态条 36px 单行,600ms 内读秒从 `18.0秒` 走到 `18.6秒`;900 → 220px 高度全程 36px、无裁剪;`prefers-reduced-motion: reduce` 下动画关闭。 - 长代码行 `horizontalOverflow: false`(换行生效);粘住的开场 / 收场围栏都渲染成正确结构,围栏之后的文字回到正文。 - 新增 / 更新的用例(逐条做过变异验证,去掉修复即红):`directProjectProcessStatus.test.tsx`、`ChatMarkdownMessage.test.tsx`(换行契约 + 五类围栏场景)、`appSurface/chat-composer.suite.ts`(`turn.started` 未到时空窗里卡片已出现且已计时)、`appSurface/project-development.suite.ts`(卡片几何契约)。 - `npx vitest run apps/ai-game-creator-shell/tests`:186 passed / 1 skipped,1860 passed / 14 skipped(当前 head 的 CI run 2902 conclusion=success);AGC `tsc --noEmit`、`npm run check:encoding`、`npm run check:doc-index`、`git diff --check` 通过。
suzmii added 1 commit 2026-09-24 16:22:30 +08:00
修复窗口变矮时对话状态条被挤扁
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m37s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m9s
Project CI / Backend tests (pull_request) Successful in 3m48s
Project CI / Frontend tests (pull_request) Successful in 2m1s
Project CI / Native shell tests (pull_request) Successful in 5m48s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 9m4s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m34s
Project CI / Repository checks (pull_request) Successful in 2m5s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 10m48s
7cdbc61ffb
- apps/ai-game-creator-shell/src/styles.css 给 .project-chat-conversation > .project-chat-process-card 补 flex: 0 0 auto:卡片带 overflow: hidden,按 flex 规范该项自动最小尺寸归零,窗口压矮时会先被压缩(实测 300px 高挤到 33px、240px 高 24px,文字被裁),而这一列里只有消息列表该被压缩
- apps/ai-game-creator-shell/src/styles.css 把这条卡片的会话列几何规则从文件末尾移到「面板纵向布局兜底」的 flex 链旁边,内缩与不可压缩合并在同一条规则里,注释说明为什么必须是 0 0 auto
- apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts 卡片契约补 flex: 0 0 auto 断言
suzmii added 1 commit 2026-09-24 16:39:14 +08:00
修复 DirectProject 对话状态条时机与 Markdown 代码块渲染
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
0daf8cdaad
- apps/ai-game-creator-shell/src/view/project-development/chat/DirectProjectChatView.tsx 状态条改为读 DirectProjectTurnStatus.displayBusy(本地命令在飞 ∪ 原生在跑),计时起点放宽到最新一个未结束回合:原先只认原生 turnRunning,而 turn.started 要等宿主应答返回才发出,模型首 token 之前那约十秒界面完全没有「正在处理」的交代
- apps/ai-game-creator-shell/src/view/project-development/chat/components/DirectProjectConversation/DirectProjectConversation.tsx 入参 nativeRunning 更名 turnInFlight 并同步注释
- apps/ai-game-creator-shell/src/components/ChatMarkdownMessage/index.tsx 块级 pre 与 code 补 whitespace-pre-wrap + break-words:窄面板里长行不再把消息拉宽、不再顶出横向滚动条
- apps/ai-game-creator-shell/src/components/ChatMarkdownMessage/index.tsx 新增 normalizeMarkdownFences:把粘在正文行里的 ``` 拆到独立行(模型常写成「…实现细节(game.js):```js」「… }```」),CommonMark 只认整行围栏,粘着的围栏会让正文被当成代码、或代码块不闭合把后续内容一起吞掉;整行/缩进围栏、行内代码、代码里的 ``` 与引用块 / 列表项开头的合法围栏都不受影响
- apps/ai-game-creator-shell/tests/ChatMarkdownMessage.test.tsx 新增粘住围栏三种场景与代码块换行契约用例
- apps/ai-game-creator-shell/tests/appSurface/chat-composer.suite.ts 补「turn.started 未到时卡片已出现且已计时」断言
- apps/ai-game-creator-shell/tests/directProjectProcessStatus.test.tsx 同步入参更名
suzmii changed title from 修复窗口变矮时 DirectProject 对话状态条被挤扁 to 修复 DirectProject 对话状态条时机与被挤扁、Markdown 代码块换行与围栏解析 2026-09-24 16:39:23 +08:00
suzmii added 1 commit 2026-09-24 16:40:49 +08:00
记录聊天 Markdown 围栏归一化的排障经验
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m31s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m0s
Project CI / Backend tests (pull_request) Successful in 4m2s
Project CI / Native shell tests (pull_request) Successful in 5m54s
Project CI / Frontend tests (pull_request) Successful in 2m7s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 8m36s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 10m5s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m49s
Project CI / Repository checks (pull_request) Successful in 2m31s
20a0d08772
- docs/project-memory/shared-memory/pitfalls.md 新增一条:模型输出会把 ``` 粘在正文行末尾,CommonMark 只认整行围栏,故必须先归一化再解析;同时记录块级 pre 与 code 都要给换行类名
suzmii added 1 commit 2026-09-24 16:57:25 +08:00
按 review 收口状态条与对话 Markdown 的容错
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m7s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m26s
Project CI / Backend tests (pull_request) Successful in 3m51s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 8m10s
Project CI / Native shell tests (pull_request) Successful in 6m3s
Project CI / Frontend tests (pull_request) Successful in 2m16s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 9m37s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m26s
Project CI / Repository checks (pull_request) Successful in 1m52s
26eb32ea22
- apps/ai-game-creator-shell/src/components/ChatMarkdownMessage/index.tsx 围栏归一化补「同一行出现第二段围栏串就跳过」判据:行内代码 `文本 ```x``` ` 的末尾那截曾被当成收场围栏拆开,凭空造出一个开场围栏、把后面的正文全变成代码
- apps/ai-game-creator-shell/src/components/ChatMarkdownMessage/index.tsx 注释补归一化顺序与行内代码判据
- apps/ai-game-creator-shell/src/view/project-development/chat/controller/useDirectProjectTurnStatus.ts 修正 displayBusy 的说明:原注释仍写着卡片只读 nativeRunning,与现状相反
- apps/ai-game-creator-shell/tests/ChatMarkdownMessage.test.tsx 新增行内代码用例(去掉新判据即红)
- docs/project-memory/shared-memory/decision-log.md 新增 2026-09-24 条:记录卡片口径翻转(更正 2026-09-22「卡片口径取保守」那条)并处置其「running 在渲染层就没有消费者」的预言,同时记录状态条几何约束与对话 Markdown 容错口径
- docs/project-memory/shared-memory/pitfalls.md 围栏归一化条补行内代码判据
suzmii merged commit c07c10c0c7 into master 2026-09-24 17:36:39 +08:00
suzmii deleted branch fix/recover-100ms 2026-09-24 17:36:39 +08:00
Sign in to join this conversation.