feat(ui): private board restrictions + scheme B assistant/user bubbles #19
|
|
@ -8,7 +8,7 @@ status: ready
|
|||
|
||||
## Summary
|
||||
|
||||
收尾私董会(@board)模块的 UI 细节与单会话状态约束,四处协同改动:(1) 在 `ChatInput.vue` 的"私董会"按钮 click 处拦截"当前会话已存在进行中的私董会"场景,弹 a-modal 提示并提供快捷新建会话按钮;(2) 将 `BoardBannerCard.vue` 从带边框/紫条/进度条/专家 chip 的重样式简化为单行标题+副标题;(3) 给 `MessageShell.vue` 中所有 `role === 'assistant'` 的消息内容添加方案 B 风格的浅灰圆角矩形气泡(F1-A 独立 token / F4-A 排除 conclusion / D4-方案1 `:empty` 隐藏);(4) 将 `UserBubble.vue` 普通文本消息改为 demo 中的深色右对齐气泡(`--color-primary` + `--text-inverse`),@board/@team 命令卡片保持现有浅色背景。改动范围仅限前端 Vue 组件与少量 store/type/token 文件,不动后端、不动方案 B 调色板、不动 StickyModeHeader 顶部条。
|
||||
收尾私董会(@board)模块的 UI 细节与单会话状态约束,四处协同改动:(1) 在 `ChatInput.vue` 的"私董会"按钮 click 处拦截"当前会话已存在进行中的私董会"场景,弹 a-modal 提示并提供快捷新建会话按钮;(2) 将 `BoardBannerCard.vue` 从带边框/紫条/进度条/专家 chip 的重样式简化为单行标题+副标题;(3) 给 `MessageShell.vue` 中所有 `role === 'assistant'` 的消息内容添加方案 B 风格的浅灰圆角矩形气泡(F1-A 独立 token / F4-A 排除所有 card-bearing 类型 / D4-方案1 `:empty` 隐藏);(4) 将 `UserBubble.vue` 普通文本消息改为 demo 中的深色右对齐气泡(`--color-primary` + `--text-inverse`),@board/@team 命令卡片保持现有浅色背景。改动范围仅限前端 Vue 组件与少量 store/type/token 文件,不动后端、不动方案 B 调色板、不动 StickyModeHeader 顶部条。
|
||||
|
||||
## Problem Frame
|
||||
|
||||
|
|
@ -38,9 +38,9 @@ status: ready
|
|||
- R9:`MessageShell.vue` 的 `.message-shell__content` 加 `background: var(--bg-message-bubble)` + `border-radius: var(--radius-md)` + `padding: var(--space-3) var(--space-4)` + `border: 1px solid var(--border-color)` + `color: var(--text-primary)`,仅 `role === 'assistant'` 时生效。**F1-A 决策**:引入独立 token `--bg-message-bubble`(light `#ffffff` / dark `#1f1f1f`),与 `--bg-secondary`(inline code/table 背景)解耦,避免气泡背景与代码/表格背景视觉冲突
|
||||
- R10:不使用 `!important`,不覆盖代码块/表格/路由 tag 样式
|
||||
- R11:不影响 `BoardRoundCard` 内 `AssistantText` 渲染
|
||||
- R12:私董会专家发言、普通 chat、@team 阶段、Debate 等都通过 `MessageShell + AssistantText` 统一获得气泡
|
||||
- R12:私董会专家发言、普通 chat 通过 `MessageShell + AssistantText` 统一获得气泡;@team 阶段使用 `TeamPlanCard`、Debate 使用 `DebateArgumentCard`/`DebateSummaryCard`/`DebateBannerCard` 等自带 card chrome 的组件(通过 `MessageShell` 渲染但不走 `AssistantText`),由 R14 排除气泡
|
||||
- R13:气泡宽度继承现有 `width: 100%; max-width: 100%`,不强制固定最大宽度
|
||||
- R14:**F4-A 决策**:气泡选择器排除 `board_conclusion` 类型——`BoardConclusionCard` 自带 card chrome(background/border/border-radius/shadow),保留其自身样式,不再被气泡包裹。实现方式:在 `MessageShell.vue` 通过 `messageType` prop 或 `:not(:has(.board-conclusion-card))` 选择器排除
|
||||
- R14:**F4-A 决策(Round 4 扩展)**:气泡选择器排除所有自带 card chrome 的 assistant 消息类型(共 9 种):`board_conclusion`(`BoardConclusionCard` → `.board-conclusion-card`,full chrome:bg + border + radius + shadow)、`team_plan`(`TeamPlanCard` → `.team-plan-card`,full chrome)、`debate_banner`(`DebateBannerCard` → `.debate-banner`,partial chrome:bg + left-border + radius)、`debate_argument`(`DebateArgumentCard` → `.debate-argument`,partial)、`debate_summary`(`DebateSummaryCard` → `.debate-summary`,partial)、`debate_resolved`(`DebateConclusionCard` → `.debate-conclusion`,partial + 4 变体 bg)、`collaboration_graph`(`CollaborationGraphCard` → `.collab-graph`,partial)、`review_result`(`ReviewResultCard` → `.review-card`,partial + 3 变体 bg)、`risk_flagged`(`RiskFlagCard` → `.risk-card`,partial)。**chrome 区分(Round 4 修正)**:仅 `BoardConclusionCard` + `TeamPlanCard` 有完整 chrome(bg + border + radius + shadow),其余 7 种只有 bg + left-border + radius(无 shadow、无 full border)。**已验证根 class 名(Round 4 R4-F1)**:注意 7 种 partial chrome 卡片 root class 名与组件名不匹配,不带 `-card` 后缀(`.debate-banner` / `.debate-argument` / `.debate-summary` / `.debate-conclusion` / `.collab-graph` / `.review-card` / `.risk-card`)。实现方式:在 `MessageShell.vue` 通过 `messageType` prop 或 `:has()` 选择器排除(具体机制依 G3 决策)。**第三种架构替代方案(Round 4 R4-A3)**:在 `MessageRenderSpec` 接口(`useMessageRenderer.ts:44-48`)新增 `bubble: boolean` 字段,在 renderer 层集中决策是否包裹气泡,避免 messageType prop 污染或 `:has()` 选择器脆弱性——见 Open Questions Round 4。**未来防护(Round 4 R4-A4)**:新增 card-bearing 类型时需手动加入 F4-A 排除列表,或采用上述 `bubble` 字段方案由 renderer 集中管理——见 Open Questions Round 4
|
||||
- R15:**D4-方案1 决策**:空 slot 内容(pre-stream thinking / tool-call-only)时气泡不渲染背景——通过 `:empty` 选择器隐藏 `background / border / padding`,仅显示 thinking dots。有内容流入后自动恢复气泡样式
|
||||
|
||||
**UserBubble 普通文本深色气泡(R16-R19)**:
|
||||
|
|
@ -55,10 +55,10 @@ status: ready
|
|||
- **私董会状态判定取 `discussing | concluding`** — `BoardState.status` 类型为 `"discussing" | "concluding" | "completed" | "dissolved"`(chatStream.ts:65 确认)。`completed | dissolved` 的旧私董会不阻塞新私董会发起,符合 origin R3 要求。
|
||||
- **"新建会话"按钮流程:`createConversation()` → `selectConversation(newId, true)`** — `createConversation()` 是同步函数(chatStore.ts:333 确认),自动设置 `currentConversationId` 但不加载服务端会话;后续 `selectConversation(newId, true)` 强制 reload 确保状态干净。不自动打开 `BoardMeetingModal`,由用户在新会话中再次点击"私董会"按钮继续(见 origin R2)。
|
||||
- **BoardBannerCard 简化为单行标题+副标题,不删除组件本身** — 保留 `BoardBannerCard.vue` 文件,仅重构 template + style。`useMessageRenderer.ts` 的 `board_started` 渲染路径不变(origin R8),保持 streaming 期间与 reload 后视觉一致。
|
||||
- **气泡样式挂在 `MessageShell.vue` 的 `.message-shell__content` 上,不挂在 `AssistantText.vue`** — `MessageShell` 是所有 assistant 消息的统一外壳,挂在这里可一次性覆盖 board_speech / board_summary / 普通聊天 / @team / Debate 等场景(origin R12),且不影响 `UserBubble.vue` 的 user 消息样式。**board_conclusion 例外**(F4-A):`BoardConclusionCard` 自带 card chrome,不被气泡包裹。
|
||||
- **气泡样式挂在 `MessageShell.vue` 的 `.message-shell__content` 上,不挂在 `AssistantText.vue`** — `MessageShell` 是所有 assistant 消息的统一外壳,挂在这里可一次性覆盖 board_speech / board_summary / 普通聊天 / @team / Debate 等场景(origin R12),且不影响 `UserBubble.vue` 的 user 消息样式。**card-bearing 类型例外(F4-A Round 4 扩展,共 9 种)**:`board_conclusion`/`team_plan`/`debate_banner`/`debate_argument`/`debate_summary`/`debate_resolved`/`collaboration_graph`/`review_result`/`risk_flagged` 渲染的 card 组件自带 card chrome(详见 R14),不被气泡包裹。
|
||||
- **气泡使用 CSS 变量,禁止硬编码** — 新增 `--bg-message-bubble: #ffffff` (light) / `#1f1f1f` (dark) 到 `tokens.css`,与 `--bg-secondary`(inline code/table 背景 `#fbfbfa`)解耦(F1-A 决策)。dark mode 自动切换。禁止硬编码 `#f3f4f6` / `#fbfbfa` / `#ffffff` 等值(project rules 硬约束)。
|
||||
- **`role === 'assistant'` 时启用气泡,`role === 'user'` 不启用** — 通过 `.message-shell--assistant .message-shell__content` 选择器限定,避免污染 user 消息的 `UserBubble` 样式。
|
||||
- **F4-A 排除 conclusion 类型** — `board_conclusion` 消息渲染的 `BoardConclusionCard` 自带 `background: var(--bg-primary)` + `border` + `border-radius: var(--radius-card)` + `box-shadow`,气泡选择器需排除该类型,避免"白卡片嵌套在白气泡里"的视觉冲突。实现方式:在 `MessageShell.vue` 增加 `messageType` prop(或 `:not(:has(.board-conclusion-card))` 选择器),conclusion 类型不加气泡样式。
|
||||
- **F4-A 排除所有 card-bearing 类型(Round 4 扩展,共 9 种)** — 排除 9 种 card-bearing assistant 消息类型:`board_conclusion`/`team_plan`/`debate_banner`/`debate_argument`/`debate_summary`/`debate_resolved`/`collaboration_graph`/`review_result`/`risk_flagged`。**chrome 区分(Round 4 修正)**:仅 `BoardConclusionCard`(`.board-conclusion-card`)+ `TeamPlanCard`(`.team-plan-card`)有完整 chrome(bg + border + radius + shadow);其余 7 种(`DebateBannerCard`→`.debate-banner`、`DebateArgumentCard`→`.debate-argument`、`DebateSummaryCard`→`.debate-summary`、`DebateConclusionCard`→`.debate-conclusion`、`CollaborationGraphCard`→`.collab-graph`、`ReviewResultCard`→`.review-card`、`RiskFlagCard`→`.risk-card`)只有 bg + left-border + radius(无 shadow、无 full border)。气泡选择器需排除这些类型,避免"card 嵌套在气泡里"的视觉冲突。实现方式:在 `MessageShell.vue` 增加 `messageType` prop(或 `:has()` 选择器),card-bearing 类型不加气泡样式。具体机制依 G3 决策。**第三种替代方案**:在 `MessageRenderSpec` 新增 `bubble: boolean` 字段由 renderer 集中决策(见 Open Questions Round 4 R4-A3)。**未来防护**:新增 card 类型需手动加入排除列表或采用 `bubble` 字段方案(见 Open Questions Round 4 R4-A4)。
|
||||
- **D4-方案1 `:empty` 隐藏空气泡** — 空 slot 内容(pre-stream thinking / tool-call-only)时通过 `:empty` 选择器隐藏 `background / border / padding`,仅显示 thinking dots 动画。有内容流入后自动恢复气泡样式,无需 JS 判断。
|
||||
- **U4 仅普通文本消息深色气泡,命令卡片保持浅色** — `UserBubble.vue` 同时渲染三种内容(普通文本 / @board|@team 命令卡片 / 文件附件),命令卡片含结构化信息(header + experts list),深色背景会降低可读性。通过 `isPlainText` computed + `.user-bubble--text` modifier 精确限定深色样式仅作用于普通文本,命令卡片和文件附件继承 `.user-bubble` 默认 `--bg-tertiary` 浅色背景。
|
||||
- **U4 用 `--color-primary` + `--text-inverse` 自动适配 dark mode** — `--color-primary` 在 light mode 为 `#1a1a1a`(深),dark mode 为 `#fbfbfa`(浅);`--text-inverse` 反之。user 气泡在 dark mode 下自动反转为浅色背景 + 深色文字,无需额外 dark mode 覆盖。
|
||||
|
|
@ -89,6 +89,7 @@ status: ready
|
|||
- `await chatStore.selectConversation(chatStore.currentConversationId!, true)`
|
||||
- 不设置 `showBoardModal.value = true`(让用户在新会话中再次点击)
|
||||
- "私董会"按钮 `@click` 改为 `handleBoardClick`
|
||||
- **焦点恢复(Round 4 R4-D3)**:a-modal 关闭时(无论"我知道了"还是"新建会话")需将焦点返回到触发按钮("私董会"按钮),符合 WAI-ARIA modal 对话模式。Ant Design Vue 的 `<a-modal>` 通过 `@cancel` / `@ok` 事件触发关闭,关闭后焦点默认落在 modal 本身;需在 `handleCreateNewConversationForBoard` 和"我知道了"按钮 click 后显式 `nextTick(() => boardButtonRef.value?.focus())`(或使用 autofocus 属性)。新建会话跳转后焦点自然落于新会话输入框,无需额外处理
|
||||
|
||||
**Patterns to follow:**
|
||||
- `ChatInput.vue:63-71` 的 `showTeamModal` 模式(v-model:open + ref + handleXxxSubmit)
|
||||
|
|
@ -164,7 +165,7 @@ status: ready
|
|||
|
||||
### U3. MessageShell 浅灰气泡(方案B)
|
||||
|
||||
**Goal:** 在 `MessageShell.vue` 的 `.message-shell__content` 上增加方案 B 风格的浅灰圆角矩形气泡样式,仅 `role === 'assistant'` 时生效,使用 CSS 变量绑定,dark mode 自动切换。**F1-A 决策**:气泡用独立 token `--bg-message-bubble`(与 inline code/table 的 `--bg-secondary` 解耦);**F4-A 决策**:排除 `board_conclusion` 类型;**D4-方案1 决策**:空内容通过 `:empty` 隐藏气泡。
|
||||
**Goal:** 在 `MessageShell.vue` 的 `.message-shell__content` 上增加方案 B 风格的浅灰圆角矩形气泡样式,仅 `role === 'assistant'` 时生效,使用 CSS 变量绑定,dark mode 自动切换。**F1-A 决策**:气泡用独立 token `--bg-message-bubble`(与 inline code/table 的 `--bg-secondary` 解耦);**F4-A 决策(Round 4 扩展,共 9 种)**:排除所有 card-bearing assistant 类型(`board_conclusion` / `team_plan` / `debate_banner` / `debate_argument` / `debate_summary` / `debate_resolved` / `collaboration_graph` / `review_result` / `risk_flagged`),这些类型由各自 card 组件自带 card chrome(2 种 full chrome + 7 种 partial chrome,详见 R14);**D4-方案1 决策**:空内容通过 `:empty` 隐藏气泡。
|
||||
|
||||
**Requirements:** R9, R10, R11, R12, R13, R14, R15
|
||||
|
||||
|
|
@ -186,7 +187,11 @@ status: ready
|
|||
padding: var(--space-3) var(--space-4);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
/* F4-A: board_conclusion 类型不加气泡,保留 BoardConclusionCard 自身 card chrome */
|
||||
/* F4-A: 所有 card-bearing assistant 类型不加气泡(共 9 种,Round 4 扩展)。
|
||||
已验证根 class 名:`.board-conclusion-card` / `.team-plan-card`(full chrome,含 shadow) /
|
||||
`.debate-banner` / `.debate-argument` / `.debate-summary` / `.debate-conclusion` / `.collab-graph` / `.review-card` / `.risk-card`
|
||||
(7 种 partial chrome,仅 bg + left-border + radius,无 shadow 无 full border;注意 root class 名与组件名不匹配,不带 -card 后缀)。
|
||||
实现期依 G3 决策扩展选择器或 messageType prop 排除列表 */
|
||||
.message-shell--assistant.message-shell--conclusion .message-shell__content,
|
||||
.message-shell--assistant:has(.board-conclusion-card) .message-shell__content {
|
||||
background: transparent;
|
||||
|
|
@ -220,7 +225,7 @@ status: ready
|
|||
- 气泡内代码块:slot 内含 `<pre><code>` → 代码块背景 `--code-bg` 不被气泡背景覆盖(视觉可区分)
|
||||
- 气泡宽度:`.message-shell__content` 计算样式 `width: 100%`,`max-width: 100%`(跟随消息列宽)
|
||||
- Dark mode:切换到 dark mode → `.message-shell__content` 计算样式 `background-color: rgb(31, 31, 31)`(`--bg-message-bubble: #1f1f1f`)
|
||||
- **F4-A 排除 conclusion**:渲染 `<MessageShell role="assistant" messageType="board_conclusion">` + `BoardConclusionCard` slot → `.message-shell__content` 计算样式 `background-color: transparent`,`border: none`(不加气泡,`BoardConclusionCard` 自身 card chrome 保留)
|
||||
- **F4-A 排除 card-bearing 类型(Round 4 扩展,共 9 种)**:分别渲染 `<MessageShell role="assistant" messageType="board_conclusion|team_plan|debate_banner|debate_argument|debate_summary|debate_resolved|collaboration_graph|review_result|risk_flagged">` + 对应 card slot(`BoardConclusionCard` / `TeamPlanCard` / `DebateBannerCard` / `DebateArgumentCard` / `DebateSummaryCard` / `DebateConclusionCard` / `CollaborationGraphCard` / `ReviewResultCard` / `RiskFlagCard`)→ 每种类型 `.message-shell__content` 计算样式 `background-color: transparent`,`border: none`(不加气泡,card 自身 chrome 保留;2 种 full chrome + 7 种 partial chrome 详见 R14)
|
||||
- **D4-方案1 空内容隐藏**:渲染 `<MessageShell role="assistant">` + 空 slot → `.message-shell__content` 计算样式 `background-color: transparent`,`border: none`,`padding: 0`(`:empty` 选择器生效)
|
||||
- **D4-方案1 有内容恢复**:渲染 `<MessageShell role="assistant">` + 非空 slot → `:empty` 不匹配,气泡样式正常应用
|
||||
- 渲染契约:样式**不**使用 `!important`
|
||||
|
|
@ -230,6 +235,7 @@ status: ready
|
|||
- 启动 Tauri 客户端,发起普通 chat,assistant 消息应有浅灰(实际为 `#ffffff` 纯白,与 `#fbfbfa` 的 inline code 区分)圆角矩形气泡
|
||||
- 发起私董会,专家发言(board_speech)应有同款气泡
|
||||
- 发起私董会,结论消息(board_conclusion)应保留 `BoardConclusionCard` 自身 card 样式,**不**被气泡包裹
|
||||
- 同理验证 `team_plan` / `debate_banner` / `debate_argument` / `debate_summary` / `debate_resolved` / `collaboration_graph` / `review_result` / `risk_flagged` 消息保留各自 card chrome(`TeamPlanCard` / `DebateBannerCard` / `DebateArgumentCard` / `DebateSummaryCard` / `DebateConclusionCard` / `CollaborationGraphCard` / `ReviewResultCard` / `RiskFlagCard`),**不**被气泡包裹(F4-A Round 4 扩展,共 9 种)
|
||||
- 切换 dark mode,气泡背景应自动变为深色(`#1f1f1f`)
|
||||
- user 消息(右侧)应显示为 demo 中的深色气泡(`--color-primary` 背景 + `--text-inverse` 白字),@board/@team 命令卡片保持现有浅色背景(见 U4)
|
||||
- assistant 消息在 thinking 阶段(空内容)不应显示空气泡矩形,仅显示三点动画
|
||||
|
|
@ -330,7 +336,7 @@ status: ready
|
|||
|
||||
- **F1(feasibility,P1)— 已决策 F1-A**:U3 气泡背景与 inline code/table 背景冲突。**决策**:引入独立 token `--bg-message-bubble`(light `#ffffff` / dark `#1f1f1f`)区分气泡背景与 inline code/table 背景(保持 `--bg-secondary: #fbfbfa`)。已固化到 R9、U3 Approach、Key Technical Decisions。**⚠️ Round 2 G5 挑战**:`#ffffff` 与 `#fbfbfa` 色差 <1% 低于 JND,且 `#ffffff` 与 `--bg-primary` 相同导致气泡仅靠边框可见——见下方 G5。
|
||||
- **F3(feasibility,P2)— 已决策 F3-A**:U2 删除 `BoardBannerCard` 的 `experts` prop 后 `useMessageRenderer.ts:145` 的 fallthrough 风险。**决策**:在 U2 Files 列表中加 `useMessageRenderer.ts`,删除 `board_banner` case 中 `experts` prop 传参。已固化到 U2 Files、U2 Approach、U2 Test scenarios。
|
||||
- **F4(feasibility,P2)— 已决策 F4-A**:U3 气泡包裹 `BoardConclusionCard` 的嵌套冲突。**决策**:气泡选择器排除 `board_conclusion` 类型,`BoardConclusionCard` 保留自身 card chrome 不被气泡包裹。已固化到 R14、U3 Approach、U3 Test scenarios、Key Technical Decisions。**⚠️ Round 2 G2/G3 挑战**:`:has()` 事实错误 + `messageType` prop 选项需 ChatMessage.vue(不在 Files)——见下方 G2/G3。
|
||||
- **F4(feasibility,P2)— 已决策 F4-A**:U3 气泡包裹 `BoardConclusionCard` 的嵌套冲突。**决策**:气泡选择器排除 `board_conclusion` 类型,`BoardConclusionCard` 保留自身 card chrome 不被气泡包裹。已固化到 R14、U3 Approach、U3 Test scenarios、Key Technical Decisions。**⚠️ Round 2 G2/G3 挑战**:`:has()` 事实错误 + `messageType` prop 选项需 ChatMessage.vue(不在 Files)——见下方 G2/G3。**⚠️ Round 3 扩展**:F4-A 排除列表从 1 种扩展到 5 种(新增 `team_plan`/`debate_banner`/`debate_argument`/`debate_summary`)。**⚠️ Round 4 扩展(R4-A1)**:进一步扩展到 9 种(新增 `debate_resolved`/`collaboration_graph`/`review_result`/`risk_flagged`),并修正 chrome 描述(2 种 full chrome + 7 种 partial chrome)。详见 R14 与 Open Questions Round 4。
|
||||
- **C2(coherence,P2)— 已应用 safe_auto**:R7 表述已修订为"删除 `.board-banner-card` 的重样式(background/border/border-radius/box-shadow)及 `__bar / __chip` 等重样式类,保留 `.board-banner-card` 容器(仅 margin/padding)+ `__title / __meta` 最小样式"。
|
||||
- **D4(design-lens,P2)— 已决策 D4-方案1**:U3 空内容气泡表现。**决策**:通过 `:empty` 选择器隐藏 `background / border / padding`,仅显示 thinking dots。已固化到 R15、U3 Approach、U3 Test scenarios、Key Technical Decisions。**⚠️ Round 2 G1 推翻**:`:empty` 永不匹配(AssistantText 总渲染根 div)——见下方 G1,实现期必须替换方案。
|
||||
|
||||
|
|
@ -372,9 +378,35 @@ status: ready
|
|||
|
||||
- **D4-R2(design-lens,P2,conf 75)— U2 简化 banner 缺乏视觉分隔**:删除所有 chrome 后,两行纯文本 banner(font-md semibold + font-xs tertiary)可能融入消息流,失去"section divider"作用。BankOutlined 图标删除后无视觉锚点。**待选方案**:(a) 保留 2px 左边框 `--accent-board`(匹配私董会身份,克制);(b) 加小色点前缀;(c) 纯排版足够("私董会 —" 文本前缀即锚点)。
|
||||
|
||||
#### Round 3 复审新增(2026-07-03)
|
||||
|
||||
**P1 manual(origin scope 边界):**
|
||||
|
||||
- **R3-A1(scope-guardian,P1,conf 100)— U4 UserBubble 深色气泡超出 origin 范围**:origin `docs/brainstorms/2026-07-02-private-board-restrictions-and-scheme-b-bubbles-requirements.md` 的 Key Decisions 明确声明"role === 'user' 的用户消息气泡保留现有 UserBubble.vue 的右对齐独立样式,不加 AssistantText 风格的浅灰块"。但本 plan U4 改动 `UserBubble.vue`,将普通文本消息改为 `--color-primary` 深色背景 + `--text-inverse` 白字的深色气泡(R16-R19),属于 origin 之外的 scope creep。**待选方案**:(a) Drop U4 及 R16-R19,保持 origin 不变(U3 仍完成 assistant 气泡统一);(b) 保留 U4 但正式 amend origin requirements doc,补充"用户普通文本消息改为深色右对齐气泡"决策。建议 (b),因为 U4 视觉冲击显著、demo 已确认方向,但需走 origin amend 流程避免 plan/origin 漂移。
|
||||
|
||||
**P2 gated_auto(事实修正):**
|
||||
|
||||
- **R3-F2(feasibility,P2,conf 50)— selectConversation `force=true` 对 local 会话不生效**:plan U1 Approach 中关于"切换会话时通过 `selectConversation(force=true)` 强制重新加载消息"的描述有事实偏差。`chatStore.ts:233` 的守卫为 `!conv?.is_local && (force || ...)`,对 `is_local=true` 的会话(含新建会话)会跳过 reload 调用——状态干净实际由 `createConversation` 保证(新建即清空 boardState/selectedExpert 等)。**建议 fix**:在 U1 Approach / Key Technical Decisions 条目中明确归因——"切换会话时 boardState 清空由 `createConversation` 在新建会话时执行;对非 local 会话调用 `selectConversation` 时 `force=true` 仍生效"。无需修改代码,仅修正 plan 文档归因。
|
||||
|
||||
#### Round 4 复审新增(2026-07-03)
|
||||
|
||||
**已应用(auto-resolve 决策汇总):**
|
||||
|
||||
- **R4-C1(coherence,P1,conf 100,safe_auto applied)** — Lines 58 & 389 "board_conclusion 例外" 已更新为 "card-bearing 类型例外(F4-A Round 4 扩展)"
|
||||
- **R4-F1(feasibility,P2,conf 75,gated_auto applied)** — 已验证 9 种 card root class 名并添加到 R14、Key Technical Decisions F4-A、U3 CSS 注释(注意 7 种 partial chrome 卡片 root class 名不带 `-card` 后缀)
|
||||
- **R4-A1(adversarial,P1,conf 100,auto-resolve applied)** — F4-A 排除列表从 5 种扩展到 9 种(新增 `debate_resolved` / `collaboration_graph` / `review_result` / `risk_flagged`)。已更新 R14、Key Technical Decisions F4-A、U3 Goal、U3 CSS 注释、U3 Test scenarios、U3 Verification
|
||||
- **R4-D1(design-lens,P2,conf 100,auto-resolve applied)** — F4-A card chrome claim 已修正:仅 `BoardConclusionCard` + `TeamPlanCard` 有完整 chrome(bg + border + radius + shadow),其余 7 种只有 partial chrome(bg + left-border + radius,无 shadow 无 full border)。已更新 R14、Key Technical Decisions F4-A、U3 CSS 注释
|
||||
- **R4-D3(design-lens,P2,conf 75,auto-resolve applied)** — U1 Approach 新增焦点恢复说明:a-modal 关闭后焦点返回"私董会"按钮(WAI-ARIA modal 对话模式)
|
||||
|
||||
**P2 manual(待后续处理):**
|
||||
|
||||
- **R4-DA1(design-lens + adversarial cross-persona promote,P2,conf 100)— 7 种 partial chrome 卡片硬编码浅色,dark mode 下与 F4-A 排除气泡后视觉冲突加剧**:`DebateBannerCard`(`#f9f0ff`)、`DebateArgumentCard`(`#fafafa`)、`DebateSummaryCard`(`#fff7e6`)、`DebateConclusionCard`(4 变体 `#fff7e6`/`#f6ffed`/`#fffbe6`/`#f5f5f5`/`#fff2f0`)、`CollaborationGraphCard`(`#f0f8ff`)、`ReviewResultCard`(3 变体 `#fafafa`/`#f6ffed`/`#fffbe6`/`#fff2f0`)、`RiskFlagCard`(`#fff7e6`)均使用硬编码浅色背景。U3 气泡用 `--bg-message-bubble` token 自动适配 dark mode,但这些 card 被 F4-A 排除后,dark mode 下仍显示硬编码浅色背景,对比度刺眼。**这是 pre-existing 问题,超出 U3 scope**(U3 仅负责气泡,不负责修复 card 颜色)。**建议**:新建独立 unit(如 U5: Card Dark Mode Adaptation)将这 7 种 card 的硬编码颜色迁移到 CSS 变量,与 U3 并行但不阻塞。或暂记为 follow-up tech debt。
|
||||
- **R4-A3(adversarial,P2,conf 75)— F4-A 遗漏第三种架构替代方案**:当前 G3 决策在 `messageType` prop 与 `:has()` 选择器间二选一。存在第三种方案:在 `MessageRenderSpec` 接口(`useMessageRenderer.ts:44-48`)新增 `bubble: boolean` 字段,在 renderer 层(`ChatMessage.vue`)集中决策是否包裹气泡,card-bearing 类型在 spec 定义时设 `bubble: false`。**优势**:新增 card 类型时无需改 `MessageShell.vue` 排除列表,避免 R4-A4 的未来防护问题;spec 集中管理,单一数据源。**劣势**:需修改 `MessageRenderSpec` 接口和所有 spec 定义点(12+ 类型),改动面比 prop/selector 方案大。**建议**:实现期若 G3 二选一难以决断,可考虑此方案作为 tie-breaker;否则记为 future refactor 候选。
|
||||
- **R4-A4(adversarial,P2,conf 75)— F4-A 排除列表对未来新增 card 类型无防护**:当前 F4-A 排除列表硬编码 9 种类型,新增 card-bearing 类型时需手动加入 `MessageShell.vue` 排除列表(prop 或 selector 方案),否则新 card 会被气泡错误包裹。**与 R4-A3 关联**:采用 `MessageRenderSpec.bubble` 字段方案可从根本上解决(renderer 集中决策),但需更大重构。**建议**:若采用 G3 prop/selector 方案,需在 `useMessageRenderer.ts` 新增 card 类型时强制走 code review checklist 验证 F4-A 排除列表是否同步更新;或采用 R4-A3 的 `bubble` 字段方案一劳永逸。
|
||||
|
||||
## System-Wide Impact
|
||||
|
||||
- **前端用户**:所有 Tauri 客户端和 Web GUI 用户将看到 (a) 私董会按钮在已有私董会的会话中弹提示而非 modal;(b) 私董会开始消息显示为简洁两行文本;(c) 所有 assistant 消息有浅灰圆角气泡(`--bg-message-bubble: #ffffff`),board_conclusion 例外(保留自身 card);(d) thinking 阶段不显示空气泡。视觉变化明显但符合方案 B 整体取向。
|
||||
- **前端用户**:所有 Tauri 客户端和 Web GUI 用户将看到 (a) 私董会按钮在已有私董会的会话中弹提示而非 modal;(b) 私董会开始消息显示为简洁两行文本;(c) 所有 assistant 消息有浅灰圆角气泡(`--bg-message-bubble: #ffffff`),card-bearing 类型例外(保留自身 card);(d) thinking 阶段不显示空气泡。视觉变化明显但符合方案 B 整体取向。
|
||||
- **后端/运维**:无影响(不动后端、不动部署、不动配置)。
|
||||
- **其他团队**:无影响(仅前端 Vue 组件)。
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue