From 6101bf8beff59e846520bd4df9885e6f2fb4be03 Mon Sep 17 00:00:00 2001 From: weichen Date: Sun, 13 Sep 2026 02:55:21 +0000 Subject: [PATCH] docs(audit): add chat history refresh diagnosis and remediation trail Record refresh disappearance root cause, gap-matrix blocker, short-term task, handoff, and archive evidence for CHAT-HISTORY-REFRESH. Co-authored-by: Cursor --- ...26-09-13-chat-history-refresh-diagnosis.md | 54 ++++++++++ ...6-09-13-chat-history-refresh-disappears.md | 99 +++++++++++++++++++ .doc/audit/INDEX.md | 8 ++ ...26-09-13-chat-history-refresh-diagnosis.md | 70 +++++++++++++ ...-09-13-chat-history-refresh-remediation.md | 57 +++++++++++ ...-09-13-chat-history-refresh-remediation.md | 65 ++++++++++++ .doc/remediation/INDEX.md | 1 + .doc/remediation/gap-matrix.md | 11 ++- .doc/status/FEATURE-MATRIX.md | 4 +- 9 files changed, 365 insertions(+), 4 deletions(-) create mode 100644 .doc/archive/ops/2026-09-13-chat-history-refresh-diagnosis.md create mode 100644 .doc/audit/2026-09-13-chat-history-refresh-disappears.md create mode 100644 .doc/ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md create mode 100644 .doc/ops/short-term/2026-09-13-chat-history-refresh-remediation.md create mode 100644 .doc/remediation/2026-09-13-chat-history-refresh-remediation.md diff --git a/.doc/archive/ops/2026-09-13-chat-history-refresh-diagnosis.md b/.doc/archive/ops/2026-09-13-chat-history-refresh-diagnosis.md new file mode 100644 index 00000000..b9b1eead --- /dev/null +++ b/.doc/archive/ops/2026-09-13-chat-history-refresh-diagnosis.md @@ -0,0 +1,54 @@ +--- +title: "刷新后对话正文消失问题定位与整改方案" +status: done +created: 2026-09-13 +updated: 2026-09-13 +owner: codex +branch: dev +worktree: "-" +mutex: chat +--- + +# 刷新后对话正文消失问题定位与整改方案 + +## 目标 + +定位页面刷新后对话正文不显示、但锚点与过滤计数仍存在的根因,并形成可执行、可验证的整改方案。 + +## 范围 + +- 前端对话状态、会话恢复、消息窗口、锚点与类别过滤的数据来源 +- 后端会话/消息持久化与历史读取 API +- 当前 dev 运行态的只读接口与数据一致性验证 +- 审计记录、整改方案与验收标准 + +## 非目标 + +- 本轮不修改业务代码 +- 不执行破坏性数据修复 +- 不把 stub 或仅内存态结果作为最终验收 + +## 步骤 + +1. [x] 复核刷新前后前端状态初始化和会话选择链路 +2. [x] 核对历史消息 API、存储字段及运行态返回 +3. [x] 解释正文、锚点和过滤计数数据源为何分叉 +4. [x] 输出 audit 与 remediation 文档并回链 + +## 验收标准 + +- [x] 根因有源码、接口或运行态证据支撑 +- [x] 明确影响范围、触发条件与风险等级 +- [x] 整改方案覆盖实现、回归测试、数据兼容和验收 + +## 相关链接 + +- Checklist: 待整改实施时建立 +- Handoff: [chat-history-refresh-diagnosis](../../ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md) +- Test report: 待整改实施并验收后建立 + +## 证据 / 备注 + +- 用户实测:新对话能正常生成文档;刷新后历史对话正文消失,但右侧锚点与顶部过滤仍显示对应消息数量。 +- Audit: [../../audit/2026-09-13-chat-history-refresh-disappears.md](../../audit/2026-09-13-chat-history-refresh-disappears.md) +- Remediation: [../../remediation/2026-09-13-chat-history-refresh-remediation.md](../../remediation/2026-09-13-chat-history-refresh-remediation.md) diff --git a/.doc/audit/2026-09-13-chat-history-refresh-disappears.md b/.doc/audit/2026-09-13-chat-history-refresh-disappears.md new file mode 100644 index 00000000..daf2a4d8 --- /dev/null +++ b/.doc/audit/2026-09-13-chat-history-refresh-disappears.md @@ -0,0 +1,99 @@ +--- +title: "刷新后对话正文消失但统计仍存在" +status: done +created: 2026-09-13 +updated: 2026-09-13 +severity: high +--- + +# 刷新后对话正文消失但统计仍存在 + +## 现象 + +用户在项目会话中可以正常与助手对话并生成文档;页面刷新后,消息正文区域显示为空,但顶部分类过滤和右侧分类锚点仍显示消息数量及首尾消息 ID。 + +结论:**消息没有从数据库删除,而是在刷新后的服务端历史恢复链路中被阶段权限过滤器全部剔除。统计接口没有应用同一权限范围,因此仍返回未过滤的数量和锚点。** + +## 根因分析 + +### 1. 刷新前与刷新后使用不同消息来源 + +- 刷新前,`web/src/App.tsx:1634-1656` 中的组件内 `messages` 保存本轮实时消息,`useChatWindow` 将它们合并到画面。 +- 刷新后,组件内 `messages` 从空数组重新开始,正文依赖 `GET /api/v1/chat/messages/window` 恢复。 +- `web/src/hooks/useChatWindow.ts:112-120` 只要服务端返回非空 `days`,就用返回桶覆盖窗口和本地缓存;即使桶中的 `messages` 已被过滤为空也照常覆盖。 + +因此,实时画面正常不代表历史恢复链路正常。 + +### 2. 文档任务消息没有绑定工作流阶段 + +- 普通聊天路径会在 `internal/chat/session.go:267-274,425-438` 把 `ActiveStageKey` 写入用户与助手消息的 `metadata.stage_key`。 +- 文档生成使用的异步任务路径在 `internal/server/task_run_handlers.go:81-96` 只写入 `project_id`、`client_turn_id`、`task_key`、`task_status`,没有写 `stage_key`、`workflow_instance_id` 或 `stage_instance_id`。 +- 任务完成投影 `internal/server/task_finalize.go:58-85` 仍未补这些作用域字段。 + +这使得文档任务在当前页面可见,但重载后无法通过阶段可见性判定。 + +### 3. 工作流激活前的历史也会被追溯性隐藏 + +- `internal/server/stage_access_helpers.go:135-163` 在项目进入受限工作流后,明确丢弃所有 `metadata.stage_key` 为空的历史消息。 +- `internal/projectinstance/stage_access.go:15-77` 根据当前 live 实例计算可见阶段;策略一旦进入 `Restricted=true`,激活前产生、天然没有阶段键的消息也无法恢复。 +- `StageKeyAllowed("")` 本身在 `internal/projectinstance/stage_access.go:103-108` 返回允许,但外层过滤器在调用它之前已经对空阶段执行 `continue`;现有单测只验证前者,没有覆盖组合行为。 + +这不是合理的“拒绝越权”,而是缺少对 `pre_activation/legacy` 对话作用域的正式建模。 + +### 4. 统计与正文的授权口径分裂 + +- 窗口和按日正文在 `internal/server/chat_window_api.go:48-50,104-106` 应用阶段过滤。 +- 分类与日期统计在同文件 `111-155` 直接查询并返回原始统计,没有会话所有权校验,也没有阶段过滤。 +- `internal/ctxmgr/chat_window.go:622-749` 的 SQL 对会话内全部未删除消息聚合,返回数量及 `MIN/MAX(id)`。 +- 前端 `CategoryFilterBar` 使用这些服务端统计显示数量;`CategoryDock` 还以统计中的首尾 ID 作为锚点兜底。因此正文为空时,数量与锚点仍存在。 + +此外,所有这些端点虽由全局中间件要求登录,但窗口、日期、分类等端点没有统一调用 `assertSessionOwnedByUser`。这会造成私聊会话对象级授权不一致,并可能泄露其他会话的消息存在性、分类数量和消息 ID。 + +## 运行态证据(dev,2026-09-13) + +只读查询 `shuimu-context-pg-dev/agent_system_dev`: + +| 项目/会话 | 结果 | +|---|---| +| project `143` | 创建者 user `9`,live instance `89`,active stage `V0.1_triage` | +| session `sess-p143-u9` | 共 4 条未删除消息,4 条正文长度均大于 0 | +| 激活前消息 `431-432` | 创建于 instance `89` 之前,无 `stage_key` | +| 文档任务消息 `433-434` | 创建于激活之后,`task_key=intake`,仍无 `stage_key` | +| 过滤结果 | 4 条均命中“空 stage_key → 丢弃”,窗口日桶保留但消息数组为空 | +| 分类统计 | 仍按全量 4 条聚合,可返回数量及首尾 ID | + +全库当前有 live 工作流实例的会话消息统计也显示:所有命中的消息均缺少 `stage_key`。这说明不是单条偶发数据,而是写入链路缺字段与历史兼容策略共同造成的系统性问题。 + +## 严重度 + +`high`,并应作为发布 blocker: + +- 核心对话记录在刷新/重新登录后不可用,用户会误认为数据丢失; +- 文档任务的对话留痕无法恢复,破坏可审计性; +- 正文、搜索、日期、统计、锚点的授权集合不一致; +- 分类数量和消息 ID 可在对象级授权不完整时形成侧信道泄露。 + +## 关联整改 + +- Remediation: [../remediation/2026-09-13-chat-history-refresh-remediation.md](../remediation/2026-09-13-chat-history-refresh-remediation.md) +- Short-term: [../ops/short-term/2026-09-13-chat-history-refresh-remediation.md](../ops/short-term/2026-09-13-chat-history-refresh-remediation.md) +- Gap matrix: [../remediation/gap-matrix.md](../remediation/gap-matrix.md) + +## 证据 + +- `web/src/App.tsx:1634-1656,3393-3506` +- `web/src/hooks/useChatWindow.ts:81-170,446-578` +- `web/src/api/chatWindow.ts:73-164` +- `internal/chat/session.go:267-280,425-468` +- `internal/server/task_run_handlers.go:76-108` +- `internal/server/task_finalize.go:58-96` +- `internal/server/stage_access_helpers.go:135-212` +- `internal/server/chat_window_api.go:12-155` +- `internal/ctxmgr/chat_window.go:39-174,622-749` +- dev PostgreSQL 只读查询(未读取或落盘消息正文) +- 相关测试通过但缺场景:`go test -short ./internal/server -run 'TestServer_ChatWindow' -count=1 -v`、`go test -short ./internal/ctxmgr -run 'TestChatWindow' -count=1 -v`、`cd web && npm test` + +## 开放问题 + +- 激活前项目私聊应默认仅对会话所有者可见,还是按项目成员和退出留痕策略共享,需要在实现前固化为策略测试;本方案建议保持现有“每人独立私聊”语义,优先按会话所有者授权。 +- 历史上若同一 `task_key` 在多个工作流实例/阶段重复出现,不能仅按当前模板名称盲目回填,必须结合运行实例、创建时间和不可变实例 ID;无法唯一归属的数据应标记为 `legacy_unscoped` 并走显式兼容策略。 diff --git a/.doc/audit/INDEX.md b/.doc/audit/INDEX.md index 103cf6cf..25b1b06e 100644 --- a/.doc/audit/INDEX.md +++ b/.doc/audit/INDEX.md @@ -13,6 +13,14 @@ ## 核心文档(按阅读顺序推荐) +### 最新专项审计(2026-09-13) + +**文件**: [2026-09-13-chat-history-refresh-disappears.md](./2026-09-13-chat-history-refresh-disappears.md) + +**结论**: 消息仍在数据库;文档任务与激活前消息缺阶段作用域,被刷新后的窗口过滤器剔除,而统计仍返回未过滤数量。 + +**整改**: [对话刷新恢复与阶段授权一致性整改方案](../remediation/2026-09-13-chat-history-refresh-remediation.md) + ### 0️⃣ 当前状态(Live SSOT) **文件**: [gap-matrix.md](../remediation/gap-matrix.md) diff --git a/.doc/ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md b/.doc/ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md new file mode 100644 index 00000000..60ab4fe3 --- /dev/null +++ b/.doc/ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md @@ -0,0 +1,70 @@ +--- +title: "对话刷新后正文消失整改实施交接" +created: 2026-09-13 +from: codex +to: next-agent +status: open +--- + +# 交接:对话刷新后正文消失整改实施 + +## 目标(下一位 Agent 应完成什么) + +按整改方案修复消息作用域、历史读取授权和统计同集问题,并完成历史回填与真实刷新 E2E。 + +## 已完成 + +- 源码链路与 dev PostgreSQL 只读定位完成,确认消息未删除。 +- 确认 project 143/session `sess-p143-u9` 的 4 条消息均缺 `stage_key`,工作流激活后被窗口过滤器全部移除。 +- 确认异步文档任务写入路径缺阶段/实例作用域;分类与日期统计未应用同一过滤。 +- 审计、整改方案、发布 blocker 与 planned short-term 已建立。 +- 现有相关 Go 测试和前端 192 项测试通过,但均未覆盖真实缺陷场景。 + +## 未完成 + +- 未修改业务代码、迁移或运行态数据。 +- 未建立实施 checklist/test-report。 +- 未运行真实 PI 刷新回归和双用户对象级授权负例。 + +## 认领 / 槽位状态 + +| 项 | 值 | +|----|-----| +| mutex 已释放 | yes | +| 集成槽位 holder | idle | +| branch | dev(诊断);建议实施用 `fix/chat-history-refresh` | +| worktree | 建议 `.worktrees/fix-chat-history-refresh` | + +## 关键文件 + +| 路径 | 说明 | +|------|------| +| `.doc/audit/2026-09-13-chat-history-refresh-disappears.md` | 根因与运行态证据 | +| `.doc/remediation/2026-09-13-chat-history-refresh-remediation.md` | 分波次整改与验收 | +| `internal/server/task_run_handlers.go` | 文档任务消息缺阶段作用域 | +| `internal/server/stage_access_helpers.go` | 空阶段消息被丢弃 | +| `internal/server/chat_window_api.go` | 正文与统计授权口径分裂 | +| `web/src/hooks/useChatWindow.ts` | 刷新后服务端空桶覆盖本地窗口 | + +## 如何验证 + +```bash +go test -short ./internal/server -run 'TestServer_ChatWindow' -count=1 -v +go test -short ./internal/ctxmgr -run 'TestChatWindow' -count=1 -v +cd web && npm test +``` + +实施时必须另加真实 PG 场景:激活前对话 → 激活 → `intake` 文档任务 → 刷新窗口,以及非 owner/无阶段职责负例。 + +## 风险 / Blocker + +- 当前为发布 blocker;刷新会造成对话“数据丢失”假象。 +- 不能用“空 `stage_key` 全部放行”或保留旧 localStorage 缓存作修复,否则会扩大阶段/跨用户泄露。 +- 历史回填存在重复 `task_key` 歧义,必须先 dry-run 并按实例与时间唯一匹配。 + +## 相关链接 + +- CURRENT: [CURRENT.md](../CURRENT.md) +- Task: [chat-history-refresh-remediation](../short-term/2026-09-13-chat-history-refresh-remediation.md) +- Audit: [chat-history-refresh-disappears](../../audit/2026-09-13-chat-history-refresh-disappears.md) +- Remediation: [chat-history-refresh-remediation](../../remediation/2026-09-13-chat-history-refresh-remediation.md) diff --git a/.doc/ops/short-term/2026-09-13-chat-history-refresh-remediation.md b/.doc/ops/short-term/2026-09-13-chat-history-refresh-remediation.md new file mode 100644 index 00000000..c1705f15 --- /dev/null +++ b/.doc/ops/short-term/2026-09-13-chat-history-refresh-remediation.md @@ -0,0 +1,57 @@ +--- +title: "修复对话刷新恢复与授权统计不一致" +status: planned +created: 2026-09-13 +updated: 2026-09-13 +owner: unassigned +branch: fix/chat-history-refresh +worktree: ".worktrees/fix-chat-history-refresh" +mutex: chat +--- + +# 修复对话刷新恢复与授权统计不一致 + +## 目标 + +按整改方案修复消息作用域写入、历史兼容、读取授权和前端恢复态,并完成真实 PostgreSQL 与 PI 文档生成后的刷新验收。 + +## 范围 + +- 消息和 task run 的不可变工作流实例/阶段作用域 +- 会话 owner 与阶段可见性的统一服务端策略 +- 窗口、日期、分类、搜索、摘要、未读、导出、锚点的同集查询 +- 现有消息 dry-run/backfill +- 前端窗口错误态和用户隔离缓存 +- 自动化与真实 PI E2E 证据 + +## 非目标 + +- 不放宽现有阶段可见性规则 +- 不用前端缓存替代服务端持久化 +- 不对无法唯一归属的历史消息盲目回填当前阶段 + +## 步骤 + +1. [ ] 先补可稳定复现本缺陷的 PG 集成与前端恢复测试 +2. [ ] 实现统一消息作用域解析与写入 +3. [ ] 实现统一会话/消息授权查询及统计同集 +4. [ ] 实现历史 dry-run/backfill 与对账 +5. [ ] 完善前端恢复状态及用户隔离缓存 +6. [ ] 执行全量门禁、真实 PI 刷新 E2E 和双用户负例 + +## 验收标准 + +- [ ] [整改方案](../../remediation/2026-09-13-chat-history-refresh-remediation.md) 的验收项全部有证据 +- [ ] `CHAT-HISTORY-REFRESH` 在 gap-matrix 中由 FAIL 更新为 PASS +- [ ] 测试报告归档并回链 + +## 相关链接 + +- Checklist: 实施开始时复制模板建立 +- Handoff: [../handoffs/2026-09-13-chat-history-refresh-diagnosis.md](../handoffs/2026-09-13-chat-history-refresh-diagnosis.md) +- Test report: 待实施 + +## 证据 / 备注 + +- Audit: [../../audit/2026-09-13-chat-history-refresh-disappears.md](../../audit/2026-09-13-chat-history-refresh-disappears.md) +- Remediation: [../../remediation/2026-09-13-chat-history-refresh-remediation.md](../../remediation/2026-09-13-chat-history-refresh-remediation.md) diff --git a/.doc/remediation/2026-09-13-chat-history-refresh-remediation.md b/.doc/remediation/2026-09-13-chat-history-refresh-remediation.md new file mode 100644 index 00000000..9dcfebd8 --- /dev/null +++ b/.doc/remediation/2026-09-13-chat-history-refresh-remediation.md @@ -0,0 +1,65 @@ +--- +title: "对话刷新恢复与阶段授权一致性整改方案" +status: planned +created: 2026-09-13 +updated: 2026-09-13 +--- + +# 对话刷新恢复与阶段授权一致性整改方案 + +## 背景 + +审计确认消息正文仍在 PostgreSQL,但文档任务消息和激活前历史缺少工作流阶段作用域;刷新后的窗口接口将其全部过滤,而分类/日期统计仍返回全量结果。详见 [审计记录](../audit/2026-09-13-chat-history-refresh-disappears.md)。 + +## 目标 + +1. 同一登录用户在权限未变化时,刷新、重新登录和服务重启后看到一致的对话正文、数量、日期、搜索和锚点。 +2. 每条新消息在服务端落库时拥有可审计的会话、项目及工作流作用域;客户端不得决定该作用域。 +3. 所有历史读取入口使用同一对象级与阶段级授权规则,统计集合必须与正文集合一致。 +4. 安全回填现有可唯一归属的消息,不丢失正文,不扩大不可确定历史的可见范围。 + +## 分波次计划 + +| 波次 | 内容 | 验收 | +|------|------|------| +| Wave 0:锁定回归 | 增加失败测试:激活前聊天 → 激活工作流 → 运行 `intake` 文档任务 → 刷新拉窗口;同时覆盖非 owner、阶段无职责用户、空阶段消息和统计一致性 | 修复前测试稳定复现“窗口 0 条、分类 4 条”;记录真实 PG 证据 | +| Wave 1:统一服务端作用域 | 在任务创建事务中由服务端从冻结实例解析 `task_key → workflow_instance_id → stage_instance_id/stage_key`;把不可变作用域写入 `task_runs` 和该回合两条 `chat_messages`;普通 chat 同样写实例 ID;finalize 只合并结果,不覆盖作用域 | 新建普通聊天和任务消息均具备正确实例/阶段;伪造客户端 stage 无效;找不到唯一阶段时拒绝启动并给出结构化错误 | +| Wave 2:修正授权查询 | 建立统一的 `AuthorizeSessionRead + visible-message predicate`,窗口、day、dates、categories、search、digest、unread、export、锚点加载全部复用;私聊先校验 owner,再计算阶段范围;统计在 SQL 层对相同可见集合聚合 | 正文、数量、首尾 ID、搜索/导出完全同集;他人 session 返回 403/404;不可见 ID 不能作锚点探测 | +| Wave 3:历史迁移 | 新增 Goose 迁移或一次性受控 backfill:任务消息通过 `task_key + task_run/workflow_run + 时间区间` 回填实例/阶段;激活前 owner 私聊标记 `scope_kind=pre_activation`;歧义数据标记 `legacy_unscoped` 并记录数量,不猜测归属 | dry-run 报告、事务执行、前后计数与 hash 对账;project 143 的 4 条消息可按策略恢复;零正文删除 | +| Wave 4:前端恢复态 | `useChatWindow` 区分 loading / authorized-empty / forbidden / error;不把“带空消息的日桶”静默呈现为空白;缓存键绑定 user/session/authorization revision,权限变化时清除,不用旧缓存绕过服务端 | 刷新不闪现上一用户/无权缓存;错误有可操作提示;服务端正常时首屏稳定落底 | +| Wave 5:全链验收 | 在空库和升级库执行 PG 集成;完成真实 PI 文档生成、浏览器刷新、重登和服务重启恢复;执行双用户/跨阶段负例 | 所有自动化门禁通过并归档 test-report;人工抽检截图/网络响应入证据 | + +## 推荐数据模型与边界 + +- `chat_messages` 增加正式列或受约束字段:`workflow_instance_id`、`stage_instance_id`、`scope_kind`;`stage_key` 可作为展示/索引冗余,不应成为唯一授权依据。 +- `task_runs` 同样保存 `workflow_instance_id`、`stage_instance_id`,确保任务运行期间阶段推进也不会改变该回合归属。 +- `scope_kind` 至少区分 `workflow_stage`、`pre_activation`、`legacy_unscoped`、`non_project_private`。 +- 消息作用域只能由服务端从会话、项目与冻结工作流实例解析;忽略客户端提交的 user/stage/instance 身份字段。 +- 不建议用“空 `stage_key` 一律允许”快速修复,这会绕过阶段隔离;也不建议仅在前端保留本地缓存,这会掩盖服务端错误并产生共享浏览器泄露风险。 + +## 建议修改范围 + +- 后端写入:`internal/server/task_run_handlers.go`、`internal/server/task_finalize.go`、`internal/chat/session.go`、`internal/taskrun/*` +- 后端读取与授权:`internal/server/chat_window_api.go`、`internal/server/chat_search_api.go`、chat digest/unread/export handlers、`internal/server/stage_access_helpers.go`、`internal/ctxmgr/chat_window.go` +- 工作流解析:`internal/projectinstance/*`,增加按冻结实例解析消息作用域的单一入口 +- 前端:`web/src/hooks/useChatWindow.ts`、`web/src/api/chatWindow.ts`、`web/src/components/chat/MessageStream.tsx` +- 数据库:`deploy/postgres/goose/00026_*`(实际序号以实施时仓库为准)及对应 dry-run/rollback 说明 + +## 验收标准 + +- [ ] 创建项目会话并发送普通消息,刷新后用户/助手两条正文、顺序、类别和锚点不变。 +- [ ] 先聊天再激活工作流,刷新后激活前 owner 私聊仍按既定策略可见。 +- [ ] 激活后通过后台任务生成文档,任务用户消息和最终助手消息刷新后完整恢复,artifact 仍可打开。 +- [ ] 工作流推进后,已参与阶段历史按策略可见,未参与阶段消息不可见。 +- [ ] `window/day/dates/categories/search/digest/unread/export` 对同一用户返回同一可见集合;统计总数等于可枚举正文数。 +- [ ] 非会话 owner 即使猜到 `session_id/message_id`,所有读取与锚点入口均返回 403/404,且不泄露计数。 +- [ ] 浏览器刷新、重新登录、切换用户、服务重启均不依赖未授权 localStorage 缓存恢复正文。 +- [ ] 历史迁移 dry-run 与执行报告包含总数、可唯一归属数、歧义数、前后校验;正文删除数为 0。 +- [ ] `go vet ./...`、`go test -short ./...`、PG 集成、`cd web && npm test && npm run build` 全绿。 +- [ ] 真实 PI Agent 文档生成后刷新恢复 E2E 有控制台/网络/数据库证据并归档 `.doc/test-reports/`。 + +## 相关链接 + +- Audit: [../audit/2026-09-13-chat-history-refresh-disappears.md](../audit/2026-09-13-chat-history-refresh-disappears.md) +- Short-term: [../ops/short-term/2026-09-13-chat-history-refresh-remediation.md](../ops/short-term/2026-09-13-chat-history-refresh-remediation.md) +- gap-matrix 行: `CHAT-HISTORY-REFRESH` diff --git a/.doc/remediation/INDEX.md b/.doc/remediation/INDEX.md index 8de77927..c6b78eeb 100644 --- a/.doc/remediation/INDEX.md +++ b/.doc/remediation/INDEX.md @@ -3,6 +3,7 @@ | 文档 | 说明 | |------|------| | [gap-matrix.md](./gap-matrix.md) | 发布缺口 SSOT | +| [2026-09-13-chat-history-refresh-remediation.md](./2026-09-13-chat-history-refresh-remediation.md) | 对话刷新恢复、消息作用域与授权统计一致性 | | [2026-09-12-comprehensive-audit-and-remediation-plan.md](./2026-09-12-comprehensive-audit-and-remediation-plan.md) | 综合缺陷与整改 | | [2026-09-12-remediation-tasks-and-acceptance-checklist.md](./2026-09-12-remediation-tasks-and-acceptance-checklist.md) | 任务拆分与验收 | | [2026-09-12-quick-reference-guide.md](./2026-09-12-quick-reference-guide.md) | 症状→原因→方案速查 | diff --git a/.doc/remediation/gap-matrix.md b/.doc/remediation/gap-matrix.md index 14d67063..99d8ac44 100644 --- a/.doc/remediation/gap-matrix.md +++ b/.doc/remediation/gap-matrix.md @@ -2,7 +2,7 @@ **更新**: 2026-09-13 **分支**: dev -**production_ready**: no(CI 真实 PI E2E / 前端人工抽检未完成;main 本地冒烟已通过) +**production_ready**: no(对话刷新恢复缺陷、CI 真实 PI E2E / 前端人工抽检未完成;main 本地冒烟已通过) **协作焦点**: [../ops/CURRENT.md](../ops/CURRENT.md) **Agent 手册**: [AGENTS.md](../AGENTS.md) · [PROJECT.md](../PROJECT.md) @@ -53,6 +53,12 @@ | DOC-SSOT | 文档叙事漂移 | PASS | 本矩阵 + superseded 标记 + ops | | OPS-AGENTS | 多 Agent 协作规范 | PASS | `AGENTS.md` / `PROJECT.md` / `.doc/ops` | +## 2026-09-13 现场问题 + +| ID | 描述 | 状态 | 证据 | 计划动作 | +|---|---|---|---|---| +| CHAT-HISTORY-REFRESH | 工作流激活后刷新,对话正文被阶段过滤器清空,但分类数量与锚点仍按全量返回 | **FAIL** | [audit](../audit/2026-09-13-chat-history-refresh-disappears.md):project 143/session `sess-p143-u9` 的 4 条正文仍在 DB、全部缺 `stage_key` | [remediation](./2026-09-13-chat-history-refresh-remediation.md):统一作用域写入、对象/阶段授权、同集统计、历史回填和真实 PI 刷新 E2E | + --- ## 发布门禁(test → main) @@ -62,10 +68,11 @@ ☑ go test -short ./... 全绿 □ TEST_DATABASE_URL 下治理 PG 集成全绿(CI) □ 真实 PI Agent 三工作流治理 E2E 实录(本轮 stub/short 已绿,PI 待 CI token) +□ 对话刷新恢复:激活前聊天 + 激活后文档任务 + 刷新/重登/重启可恢复,双用户负例通过 ☑ lifecycle fix SQL 已在 dev 执行 ☑ test/dev health schema_version=25 ☑ main 环境部署冒烟(本地 8000 health/ready schema 25) □ 前端:版本冲突刷新、终止 preview 人工抽检 ``` -**结论**: P0 授权、冷启动序列、Go 门禁、三环境本地冒烟已闭环。**发布 blocker 剩余 CI 真实 PI E2E 与前端人工抽检**。 +**结论**: P0 授权、冷启动序列、Go 门禁、三环境本地冒烟已闭环;新增现场缺陷 `CHAT-HISTORY-REFRESH`。**发布 blocker 包括对话刷新恢复、CI 真实 PI E2E 与前端人工抽检**。 diff --git a/.doc/status/FEATURE-MATRIX.md b/.doc/status/FEATURE-MATRIX.md index 6222f84f..053d0ab0 100644 --- a/.doc/status/FEATURE-MATRIX.md +++ b/.doc/status/FEATURE-MATRIX.md @@ -16,10 +16,10 @@ | 模块 | 能力 | 状态 | 证据 | 缺口/后续 | mutex | |------|------|------|------|-----------|-------| | 意图识别 L1 | 18 类 Intent + 三分支消解 | done | [system-design/intent-recognition](../system-design/intent-recognition/);[test-report 2026-09-07](../test-reports/2026-09-07-three-branch-intent-framework-test-report.md) | — | `intent` | -| 对话 / ctxmgr | 多轮上下文、记忆、摘要 | partial | [system-design/multi-turn-dialogue](../system-design/multi-turn-dialogue/);P0 断链已修 | 语义摘要(D5 backlog);长任务治理 | `chat` | +| 对话 / ctxmgr | 多轮上下文、记忆、摘要 | partial | [system-design/multi-turn-dialogue](../system-design/multi-turn-dialogue/);[刷新恢复专项审计](../audit/2026-09-13-chat-history-refresh-disappears.md) | `CHAT-HISTORY-REFRESH`:作用域写入、同集授权统计、历史回填;语义摘要(D5 backlog) | `chat` | | 智能体小队 | 角色-任务-工作区-黑板 | done | [system-design/agent-squad](../system-design/agent-squad/);[test 2026-09-07](../test-reports/2026-09-07-dynamic-squad-planning-test-report.md) | 非关键步骤降级(A5/A6 backlog) | `squad` | | 工作流治理 | 三正式工作流 + 阶段门禁 | done | [remediation/three-workflows](../remediation/2026-09-12-three-workflows-strict-governance-remediation.md);[test 2026-09-12](../test-reports/2026-09-12-three-workflows-governance-remediation-test-report.md) | Phase2 设计器 partial | `workflow` | -| IAM / 鉴权 | 项目级 API 鉴权 + RBAC | done | [audit/authorization](../audit/authorization-matrix-v2.md);[test phase1](../test-reports/2026-09-12-phase1-iam-authz-test-report.md) | 旧 API 410 标注(BUG-11 partial) | `authz` | +| IAM / 鉴权 | 项目级 API 鉴权 + RBAC | partial | [audit/authorization](../audit/authorization-matrix-v2.md);[刷新恢复专项审计](../audit/2026-09-13-chat-history-refresh-disappears.md) | 历史读取端点补统一会话 owner + 阶段授权;旧 API 410 标注(BUG-11 partial) | `authz` | | 文档治理 | 法定文档生命周期 + 租约 | done | [test docgov](../test-reports/2026-09-08-docgov-lifecycle-and-claiming-framework-test-report.md) | — | `docgov` | | 前端工作台 | 三栏 + 块文档 + SSE | partial | [test workbench](../test-reports/2026-09-08-three-column-workbench-and-block-document-test-report.md) | 人工抽检待完成 | `web` | | PI Runner / 配置链 | pi-agent + MiniMax 真实链路 | done | [test piagent](../test-reports/2026-09-13-codex-audit-p0-remediation-test-report.md);[container-env](../test-reports/2026-09-13-container-env-configuration-test-report.md) | — | `pi-agent` |