diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index d4d1bc25..4ee154bb 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -2832,3 +2832,19 @@ - 防复发:引擎适配器必须有真实响应形状的契约测试;新增任何映射层必须对照 `scripts/rectification/contracts.py:SCOREABLE_EVENT_KINDS`;RPC 重放/幂等语义以“先重放后校验、重放校验已落库状态”为唯一实现顺序;迁移修改必须在真实 PostgreSQL 上从空库全量应用并重跑。 - 相关记录:BUG-163、BUG-112 - 修复版本:本地 staging 候选(未 push / deploy) + +## BUG-165 | 合并咨询 Agentic runtime 后生时校正执行步骤复用共享 activity 字段导致构建失败 + +- 状态:resolved(local candidate,待 staging gate) +- 首次发现:2026-08-11 +- 最近更新:2026-08-11 +- 影响面:`RectificationAgenticChat`、共享 `ChatMessageView`、Next.js production type-check +- 用户现象:生时校正与最新 staging 的咨询 Agentic runtime 单独测试均通过,但合并后 `next build` 在 `rectification-agentic-chat.tsx` 报 `string[]` 不能赋给结构化 `AgentActivityView`。 +- 触发条件:将 V9 生时校正分支合入包含咨询 Agentic runtime 的最新 `origin/staging`,再运行 production build。 +- 根因:并行开发期间,共享 `ChatMessageView.activity` 从通用状态扩展为咨询 runtime 使用的单个 `{ phase, label }`;生时校正把执行回执的多步骤 `string[]` 也命名为 `activity`。聚焦源码/运行测试没有跨两个 runtime 做 TypeScript 组合检查,只有 production build 暴露交叉类型冲突。 +- 修复:生时校正的持久化/流式回执步骤改为独立 `receiptActivity: readonly string[]`,只用于折叠的“本轮做了什么”;共享 `activity` 继续由咨询 runtime 独占并保持 `{ phase, label }` 合同,不改其 UI 与状态映射。 +- 验证:合并最新 staging 后,`rectification-v9-stream`、`rectification-agentic-entry`、`chat-stream-layout` 共 36/36 通过;目标 ESLint 通过;Next.js 16.2.10 production build 完成 type-check、60 个静态页面生成与 route 列表收口;`git diff --check` 通过。 +- 防复发:生时校正执行回执与咨询即时 activity 必须使用不同字段;任何同时修改 `ChatMessageView` 与专用聊天 surface 的分支,合并最新 staging 后必须运行共享 layout 测试和 production build,不能只依赖各自聚焦测试。 +- 相关记录:BUG-162、BUG-163、BUG-164 +- 复发自:无(并行 runtime 合并冲突) +- 修复版本:本次 staging 候选 diff --git a/frontend/src/components/rectification-agentic-chat.tsx b/frontend/src/components/rectification-agentic-chat.tsx index 613fdbc2..e0be9cce 100644 --- a/frontend/src/components/rectification-agentic-chat.tsx +++ b/frontend/src/components/rectification-agentic-chat.tsx @@ -57,7 +57,8 @@ type RectificationAgenticChatProps = Readonly<{ type RenderMessage = ChatMessageView & { renderKey: string; - activity?: readonly string[]; + /** V9 execution-receipt steps; separate from shared consultation activity. */ + receiptActivity?: readonly string[]; receiptStatus?: string; }; @@ -119,7 +120,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) { text: turn.text ?? "", renderKey: key, state: turn.status === "completed" ? "settled" : "thinking", - activity: activityFromReceipt(turn.receipt), + receiptActivity: activityFromReceipt(turn.receipt), receiptStatus: turn.receipt?.status, }]; } @@ -212,7 +213,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) { ...(action === "message" ? [{ role: "user", text: trimmed, renderKey: userRenderKey, state: "settled" } satisfies RenderMessage] : []), - { role: "assistant", text: "", renderKey: assistantRenderKey, state: "thinking", activity: [] }, + { role: "assistant", text: "", renderKey: assistantRenderKey, state: "thinking", receiptActivity: [] }, ]); setDraft(""); @@ -293,7 +294,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) { activitySet.add(event.type); liveActivity = [...liveActivity, labelForPhase(event.type)]; setMessages((current) => current.map((message) => message.renderKey === assistantRenderKey - ? { ...message, activity: liveActivity } + ? { ...message, receiptActivity: liveActivity } : message)); } } @@ -304,7 +305,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) { const succeeded = completed && !streamFailed && Boolean(parsed.text); setMessages((current) => succeeded ? current.map((message) => message.renderKey === assistantRenderKey - ? { ...message, text: parsed.text, suggestions: parsed.suggestions, state: "settled", activity: liveActivity } + ? { ...message, text: parsed.text, suggestions: parsed.suggestions, state: "settled", receiptActivity: liveActivity } : message) : current.filter((message) => message.renderKey !== assistantRenderKey)); setSuggestions(succeeded ? parsed.suggestions : []); @@ -386,11 +387,11 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) { {messages.map((message) => (