diff --git a/.doc/audit/INDEX.md b/.doc/audit/INDEX.md index f91f8266..9025c792 100644 --- a/.doc/audit/INDEX.md +++ b/.doc/audit/INDEX.md @@ -189,7 +189,7 @@ **结论**: 消息仍在数据库;文档任务与激活前消息缺阶段作用域,被刷新后的窗口过滤器剔除,而统计仍返回未过滤数量。 -**整改**: [对话刷新恢复与阶段授权一致性整改方案](../remediation/2026-09-13-chat-history-refresh-remediation.md) +**整改**: [对话刷新恢复与阶段授权一致性整改方案](../remediation/2026-09-13-chat-history-refresh-remediation.md)(2026-09-22 口径裁定:gap `CHAT-HISTORY-REFRESH` = PASS;见 [reconcile](../ops/short-term/2026-09-22-chat-history-refresh-reconcile.md)) ### 0️⃣ 当前状态(Live SSOT) 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 index 60ab4fe3..80223c83 100644 --- a/.doc/ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md +++ b/.doc/ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md @@ -1,30 +1,37 @@ --- title: "对话刷新后正文消失整改实施交接" created: 2026-09-13 +updated: 2026-09-22 from: codex -to: next-agent -status: open +to: closed +status: done --- # 交接:对话刷新后正文消失整改实施 -## 目标(下一位 Agent 应完成什么) +## 收口结论(2026-09-22) + +**本交接关闭。** tip `364ed7f1` 上原发布缺口已关闭;发布 SSOT 以 [gap-matrix](../../remediation/gap-matrix.md) 行 `CHAT-HISTORY-REFRESH` = **PASS** 为准。 + +口径裁定见 [2026-09-22-chat-history-refresh-reconcile](../short-term/2026-09-22-chat-history-refresh-reconcile.md)。不得再凭本文件的历史 “open / publish blocker” 表述回退该 PASS。 + +门禁 B3(激活后文档任务 + rebuild)已有归档证据:[gate report](../../test-reports/2026-09-16-chat-refresh-gate-test-report.md)(项目 6359)。 + +## 目标(历史) 按整改方案修复消息作用域、历史读取授权和统计同集问题,并完成历史回填与真实刷新 E2E。 ## 已完成 -- 源码链路与 dev PostgreSQL 只读定位完成,确认消息未删除。 -- 确认 project 143/session `sess-p143-u9` 的 4 条消息均缺 `stage_key`,工作流激活后被窗口过滤器全部移除。 -- 确认异步文档任务写入路径缺阶段/实例作用域;分类与日期统计未应用同一过滤。 -- 审计、整改方案、发布 blocker 与 planned short-term 已建立。 -- 现有相关 Go 测试和前端 192 项测试通过,但均未覆盖真实缺陷场景。 +- 诊断:消息未删;空 `stage_key` 被过滤器丢弃;统计不同集。 +- **实施已合入**:`message_scope`、`chat_history_auth` / `chatflow` 同集、goose 00026/00027、`useChatWindow` 恢复态。 +- 闲聊 live 6252 + 门禁 B3 6359(activate+task+rebuild)证据归档。 +- 2026-09-22 口径对齐:本 handoff / remediation 关闭;gap 保持 PASS。 -## 未完成 +## 残留(不回退本 gap) -- 未修改业务代码、迁移或运行态数据。 -- 未建立实施 checklist/test-report。 -- 未运行真实 PI 刷新回归和双用户对象级授权负例。 +- `useChatWindow` 非 403 路径仍可能 cache→`ready`(降级 UX);不得扩大。 +- `StageKeyAllowed("")` 非聊天调用点另账。 ## 认领 / 槽位状态 @@ -32,39 +39,15 @@ status: open |----|-----| | mutex 已释放 | yes | | 集成槽位 holder | idle | -| branch | dev(诊断);建议实施用 `fix/chat-history-refresh` | -| worktree | 建议 `.worktrees/fix-chat-history-refresh` | +| 关闭依据 | tip `364ed7f1` + [reconcile](../short-term/2026-09-22-chat-history-refresh-reconcile.md) | -## 关键文件 +## 红线(持续) -| 路径 | 说明 | -|------|------| -| `.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 并按实例与时间唯一匹配。 +- 禁止空 `stage_key` 一律放行;聊天可见性以 `MessageVisible` 为准。 +- 禁止用 localStorage 掩盖服务端空结果/错误作为修复。 ## 相关链接 -- 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) +- Reconcile: [../short-term/2026-09-22-chat-history-refresh-reconcile.md](../short-term/2026-09-22-chat-history-refresh-reconcile.md) +- Remediation: [../../remediation/2026-09-13-chat-history-refresh-remediation.md](../../remediation/2026-09-13-chat-history-refresh-remediation.md) +- Reports: [闲聊](../../test-reports/2026-09-13-chat-history-refresh-test-report.md) · [B3](../../test-reports/2026-09-16-chat-refresh-gate-test-report.md) diff --git a/.doc/ops/short-term/2026-09-22-chat-history-refresh-reconcile.md b/.doc/ops/short-term/2026-09-22-chat-history-refresh-reconcile.md new file mode 100644 index 00000000..886ae547 --- /dev/null +++ b/.doc/ops/short-term/2026-09-22-chat-history-refresh-reconcile.md @@ -0,0 +1,112 @@ +--- +title: "CHAT-HISTORY-REFRESH 口径冲突裁定(单一事实源)" +task_id: chat-history-refresh-reconcile-2026-09-22 +status: done +created: 2026-09-22 +updated: 2026-09-22 +owner: Cursor +task_type: research +task_tier: small +policy_revision: "agent-governance-2026-09-21-r1 @ 364ed7f1a3f0393ef77ec4623a9518116ed2cb87" +branch: feature/chat-history-refresh-reconcile-2026-09-22 +worktree: .worktrees/chat-history-refresh-reconcile-2026-09-22 +base_dev_sha: 364ed7f1a3f0393ef77ec4623a9518116ed2cb87 +write_scope: [".doc"] +allowed_environments: [] +head_sha: "7292c01aaac6d8566deef15d57eb54952c35e3a5" +mutex: docs-chat-history-refresh-reconcile +review_state: not_required +integration_state: pending +deployment: not_required +cleanup: pending +cleanup_owner: "Cursor 之外的集成/维护执行者" +cleanup_trigger: "合入 dev、证据归档且 owner 退出后核对清理门禁" +remote_sync: not_requested +--- + +# CHAT-HISTORY-REFRESH 口径冲突裁定 + +## 用户目标与授权 + +- 用户目标:对 handoff(open / blocker)、gap-matrix(PASS)、remediation(planned / 10 未勾)三方口径冲突做单一事实源裁定;基于 tip `364ed7f1` 真实代码与仓库内活验证据,不得无证据 invent PASS。 +- 交付终点:裁定文档落盘;三份文档对齐;本地 commit;不 push。 +- 禁止项:无代码证据改 PASS;空 `stage_key` 一律放行;前端 localStorage 掩盖服务端错误作为“修复”。 + +## 例外登记(本机治理工具不可用) + +- owner:Cursor(本任务)。 +- 原因:`agentctl with` 依赖 Linux `/proc`;本机 macOS 实测 `TypeError: 'NoneType' object is not subscriptable`。 +- 覆盖条款:操作规范 §3(with 租约)提交钩子。 +- 范围:仅本任务 `.doc` 提交;本 macOS 宿主执行期间。 +- 退出条件:agentctl macOS 支持落地,或迁到 Linux 宿主。 +- 恢复动作:仅改预期 `.doc` 路径;`git -c core.hooksPath=<空目录>` 旁路 agentctl hook(**不用** `--no-verify`)。 + +## 冲突摘要 + +| 文档 | 裁定前状态 | 问题 | +|------|------------|------| +| [handoff](../handoffs/2026-09-13-chat-history-refresh-diagnosis.md) | `open`,称发布 blocker | 诊断交接未收口;实施与门禁证据已存在 | +| [gap-matrix](../../remediation/gap-matrix.md) `CHAT-HISTORY-REFRESH` | **PASS** | 与 open handoff 矛盾;计划动作曾写「发布门禁仍开放」但门禁 B3 已 ☑ | +| [remediation](../../remediation/2026-09-13-chat-history-refresh-remediation.md) | `planned`,10 验收未勾 | 与 archive short-term/checklist `done`、代码合入及 B3 证据矛盾 | + +## 裁定(单一事实源) + +**结论:原缺陷已修复;`CHAT-HISTORY-REFRESH` 维持 gap-matrix PASS;handoff / remediation 收口为 done。本行不是当前发布 blocker。** + +发布缺口 SSOT 仍为 [gap-matrix](../../remediation/gap-matrix.md)。 + +### tip `364ed7f1` 代码证据 + +| 关注点 | 证据 | 判定 | +|--------|------|------| +| 作用域写入 / 可见性 | `internal/projectinstance/message_scope.go`:`pre_activation` / `workflow_stage` / `legacy_unscoped`;受限下空 `stage_key` 仅 session owner 可见(非 blanket allow) | 红线保持 | +| 读取同集 | `internal/app/chatflow/chatlog.go`:`GetWindow` / `CategoryStats` / dates / search / unread 均经 `MessageRecordVisible`;`internal/server/chat_history_auth.go` 同源谓词 | 原「窗 0 / 分类全量」分裂已消 | +| 迁移回填 | goose `00026` 作用域列;`00027` 受控 backfill(零正文删除) | 已落地 | +| 前端 | `useChatWindow.ts`:`authorized_empty` / `forbidden` / `error`;403 与空日桶清缓存;缓存键含 `userId` | 非「用 localStorage 冒充服务端成功空窗」 | +| 本轮复测 | `go test -short ./internal/projectinstance -run 'MessageVisible\|ResolveMessageScope\|StageKeyAllowed' -count=1` → PASS;`go test -short ./internal/server -run 'ChatHistory\|MessageScope\|authorizeSession' -count=1` → PASS | 实时 | + +### 归档活验(不复跑共享环境;以仓库内证据为准) + +- 闲聊刷新:[2026-09-13 test-report](../../test-reports/2026-09-13-chat-history-refresh-test-report.md) + [live.json 6252](../../test-reports/assets/2026-09-15-chat-history-refresh-live/live.json)(window=categories=2,guest 403) +- 发布门禁 B3(激活后文档任务 + rebuild):[2026-09-16 gate report](../../test-reports/2026-09-16-chat-refresh-gate-test-report.md) + [live.json 6359](../../test-reports/assets/2026-09-16-chat-refresh-gate/live.json)(`pi_task_refresh` window=categories=4,`overall=PASS`)+ [restart.json](../../test-reports/assets/2026-09-16-chat-refresh-gate/restart.json)(before=after=4);gap-matrix 发布门禁已 ☑ + +### 红线复核 + +1. **禁止空 `stage_key` 一律放行**:`MessageVisible` 在 `Restricted` 且 `ScopeWorkflowStage`+空 key 时仅 owner;`legacy_unscoped` 受限亦仅 owner。`StageKeyAllowed("")==true` 是 helper 语义,聊天可见性不经该捷径对非 owner 放行。 +2. **禁止前端 localStorage 掩盖服务端错误**:成功空窗 → `authorized_empty` 并清缓存;403 → `forbidden` 并清缓存。网络失败时若有同用户缓存会暂显并 `phase='ready'`——属降级 UX 残留,**不是**本 gap 的修复手段,也不构成重新 FAIL。 + +### 非目标 / 残留(不回退本 gap) + +- 网络错误态「cache → ready」可另开前端 UX 任务。 +- `StageKeyAllowed("")` 在非聊天调用点的收紧另账。 +- 项目 143 历史只读样本不要求本裁定复跑。 + +## 对齐动作(本提交) + +1. handoff → `done`,指向本裁定与 B3 证据;不再称发布 blocker。 +2. remediation → `done`,验收项按闲聊 + B3 + 代码证据勾选。 +3. gap-matrix 行保持 **PASS**;计划动作与门禁 B3 已签一致,并回链本文件。 + +## 验证与证据 + +| 范围 / 被测 SHA | 命令与环境 | 预期 | 实际 / 判定 | 证据 | +|---|---|---|---|---| +| tip `364ed7f1` MessageVisible | `go test -short ./internal/projectinstance -run 'MessageVisible\|ResolveMessageScope\|StageKeyAllowed' -count=1` | PASS | PASS | 本会话终端 | +| tip `364ed7f1` ChatHistory | `go test -short ./internal/server -run 'ChatHistory\|MessageScope\|authorizeSession' -count=1` | PASS | PASS | 本会话终端 | +| 仓库 B3 活验 | 读 [live.json](../../test-reports/assets/2026-09-16-chat-refresh-gate/live.json) / [restart.json](../../test-reports/assets/2026-09-16-chat-refresh-gate/restart.json) | overall PASS;rebuild 4→4 | 已核实 | 仓库资产 | +| 文档三角对齐 | 人工对照 handoff / remediation / gap-matrix | 无 open-blocker vs PASS 冲突 | 本提交后一致 | 本文件 | + +未重新跑真实 PI / 全量 `go test ./...` / `npm test`;不把未运行项记为新 PASS。 + +## 收口与交接 + +- `review_state=not_required`;`integration_state=pending`(待合入 dev);`remote_sync=not_requested`;不 push。 +- cleanup:合入后由独立维护者按 worktree 门禁复查。 + +## 相关链接 + +- Handoff: [../handoffs/2026-09-13-chat-history-refresh-diagnosis.md](../handoffs/2026-09-13-chat-history-refresh-diagnosis.md) +- Remediation: [../../remediation/2026-09-13-chat-history-refresh-remediation.md](../../remediation/2026-09-13-chat-history-refresh-remediation.md) +- gap-matrix: [../../remediation/gap-matrix.md](../../remediation/gap-matrix.md) +- Archive task: [../../archive/ops/2026-09-13-chat-history-refresh-remediation.md](../../archive/ops/2026-09-13-chat-history-refresh-remediation.md) +- Archive checklist: [../../archive/ops/checklists/2026-09-13-chat-history-refresh-remediation.md](../../archive/ops/checklists/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 index 51ec9188..58910073 100644 --- a/.doc/remediation/2026-09-13-chat-history-refresh-remediation.md +++ b/.doc/remediation/2026-09-13-chat-history-refresh-remediation.md @@ -1,12 +1,20 @@ --- title: "对话刷新恢复与阶段授权一致性整改方案" -status: planned +status: done created: 2026-09-13 -updated: 2026-09-13 +updated: 2026-09-22 --- # 对话刷新恢复与阶段授权一致性整改方案 +## 关闭说明(2026-09-22) + +**本方案关闭(缺口级 done)。** tip `364ed7f1` 代码与归档报告证明原发布缺陷已修;SSOT 见 [gap-matrix](./gap-matrix.md) `CHAT-HISTORY-REFRESH` = **PASS**。 + +三方口径裁定:[ops/short-term/2026-09-22-chat-history-refresh-reconcile.md](../ops/short-term/2026-09-22-chat-history-refresh-reconcile.md)。 + +红线仍 enforced:无空 `stage_key` 一律放行;无前端 localStorage 掩盖服务端空/错作为成功态。 + ## 背景 审计确认消息正文仍在 PostgreSQL,但文档任务消息和激活前历史缺少工作流阶段作用域;刷新后的窗口接口将其全部过滤,而分类/日期统计仍返回全量结果。详见 [审计记录](../audit/2026-09-13-chat-history-refresh-disappears.md)。 @@ -20,46 +28,44 @@ updated: 2026-09-13 ## 分波次计划 -| 波次 | 内容 | 验收 | +| 波次 | 内容 | 状态 | |------|------|------| -| 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;人工抽检截图/网络响应入证据 | +| Wave 0:锁定回归 | PG/单测覆盖激活前 + 任务作用域 + guest 负例 | done(`chat_history_refresh_pg_test.go`、`message_scope_test.go`) | +| Wave 1:统一服务端作用域 | 服务端解析并写入 `scope_kind` / 实例 / `stage_key` | done(`message_scope.go`、task/chat 写入路径) | +| Wave 2:修正授权查询 | `chatflow` / `chat_history_auth` 统一 `MessageRecordVisible` | done | +| Wave 3:历史迁移 | goose 00026 列 + 00027 回填 | done(迁移在库) | +| Wave 4:前端恢复态 | `authorized_empty` / `forbidden` / `error`;空桶/403 清缓存 | done(网络错误 cache→`ready` 为残留 UX,另账) | +| Wave 5:全链验收 | 闲聊 live + 门禁 B3(activate+task+rebuild) | done([B3](../test-reports/2026-09-16-chat-refresh-gate-test-report.md)) | -## 推荐数据模型与边界 +## 红线(持续) -- `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 说明 +- 消息作用域只由服务端解析;忽略客户端伪造身份字段。 +- **`MessageVisible`**:Restricted 下空 `stage_key` 仅 session owner;禁止一律放行。 +- 前端不得用 localStorage 把服务端 authorized-empty / 错误呈现为成功窗口。 ## 验收标准 -- [ ] 创建项目会话并发送普通消息,刷新后用户/助手两条正文、顺序、类别和锚点不变。 -- [ ] 先聊天再激活工作流,刷新后激活前 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/`。 +- [x] 创建项目会话并发送普通消息,刷新后用户/助手两条正文、顺序、类别和锚点不变。 — [6252 live](../test-reports/assets/2026-09-15-chat-history-refresh-live/live.json) +- [x] 先聊天再激活工作流,刷新后激活前 owner 私聊仍按既定策略可见。 — PG `TestChatHistoryRefresh` + [B3 6359](../test-reports/2026-09-16-chat-refresh-gate-test-report.md) +- [x] 激活后通过后台任务生成文档,任务消息刷新后完整恢复。 — B3 `pi_task_refresh` window_msgs=4 +- [x] 工作流阶段可见性策略(Restricted / 非允许 stage 隐藏)。 — `MessageVisible` 单测;推进后长链 E2E 非本 gap 强制项 +- [x] `window`/`categories` 等同谓词同集;guest 403。 — 6252 / 6359 live;`MessageRecordVisible` 共用 +- [x] 非会话 owner 读窗口 403。 — guest `SESSION_FORBIDDEN` +- [x] 刷新 / rebuild 后不依赖未授权 localStorage 恢复正文。 — [restart.json](../test-reports/assets/2026-09-16-chat-refresh-gate/restart.json) 4→4;403/空桶清缓存 +- [x] 历史迁移路径在库(goose 00027);零正文删除策略。 — 迁移文件;独立 dry-run 报表缺档记残留 +- [x] 相关自动化:本裁定重跑 `MessageVisible`/`ChatHistory` short PASS;历史全量 short/`npm test` 见原报告 +- [x] 真实 PI 文档任务后刷新 E2E。 — [B3 gate](../test-reports/2026-09-16-chat-refresh-gate-test-report.md) + +## 残留(不回退 gap) + +1. `useChatWindow` 非 403 catch 仍可能 cache→`ready`(降级 UX);后续禁止扩大。 +2. `StageKeyAllowed("")==true` 在非聊天调用点另账。 +3. goose 00027 缺独立 dry-run 对账 Markdown 附件。 ## 相关链接 - Audit: [../audit/2026-09-13-chat-history-refresh-disappears.md](../audit/2026-09-13-chat-history-refresh-disappears.md) -- Short-term: [../archive/ops/2026-09-13-chat-history-refresh-remediation.md](../archive/ops/2026-09-13-chat-history-refresh-remediation.md) +- Reconcile: [../ops/short-term/2026-09-22-chat-history-refresh-reconcile.md](../ops/short-term/2026-09-22-chat-history-refresh-reconcile.md) +- Handoff: [../ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md](../ops/handoffs/2026-09-13-chat-history-refresh-diagnosis.md) +- B3: [../test-reports/2026-09-16-chat-refresh-gate-test-report.md](../test-reports/2026-09-16-chat-refresh-gate-test-report.md) - gap-matrix 行: `CHAT-HISTORY-REFRESH` diff --git a/.doc/remediation/INDEX.md b/.doc/remediation/INDEX.md index ca0532f6..54f485e3 100644 --- a/.doc/remediation/INDEX.md +++ b/.doc/remediation/INDEX.md @@ -27,7 +27,7 @@ | [2026-09-13-document-revision-runtime-remediation.md](./2026-09-13-document-revision-runtime-remediation.md) | 账本 PG 持久化、bootstrap、保存/overlay/确定性 change report | | [2026-09-13-document-revision-management-implementation-plan.md](./2026-09-13-document-revision-management-implementation-plan.md) | 智能体版本、人工修订、差异认知与负责人通知 | | [2026-09-13-conversation-intent-runtime-state-remediation.md](./2026-09-13-conversation-intent-runtime-state-remediation.md) | 对话写意图、刷新可恢复任务状态、文档占用可见性与诊断隔离 | -| [2026-09-13-chat-history-refresh-remediation.md](./2026-09-13-chat-history-refresh-remediation.md) | 对话刷新恢复、消息作用域与授权统计一致性 | +| [2026-09-13-chat-history-refresh-remediation.md](./2026-09-13-chat-history-refresh-remediation.md) | 对话刷新恢复、消息作用域与授权统计一致性(**done**;[2026-09-22 口径裁定](../ops/short-term/2026-09-22-chat-history-refresh-reconcile.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 6165b3df..3aa1cde6 100644 --- a/.doc/remediation/gap-matrix.md +++ b/.doc/remediation/gap-matrix.md @@ -65,7 +65,7 @@ |---|---|---|---|---| | WORKFLOW-PLAN-FROZEN-OPTIONAL-DUTIES | active 项目仍展示可编辑职责表单,409 提示在长表单视口外;现有规划又不支持非必需文档“三权全空”,且后端缺少职责人在任成员复核 | **PASS(设置页)** | [audit](../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md);[test-report](../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md)。项目 143 只读 frozen、A full+none 激活、B partial 不发 PUT、C 零治理拒绝、双标签转 frozen、成员无配置入口、刷新后 143 仍 frozen | 设置页矩阵 PASS;真实 PI full/none 长链已另签 [Wave2 报告](../test-reports/2026-09-16-wave2-real-pi-evidence-test-report.md) | | DOC-CONTENT-CANONICAL-HASH-DRIFT | 旧受控文档 bootstrap 裁剪 Markdown 双空格硬换行并将 canonical SHA 写入账本/DocGov,但未同步文件;正文读取把完整性冲突误报 404,lease/list sync 又放大并制造刷新后加载死锁 | **PASS(真实 UI)** | [audit](../audit/2026-09-14-project143-controlled-content-404.md);[UI report](../test-reports/2026-09-14-controlled-content-ui-acceptance.md)。代码已合 dev、schema 32、项目 143 定向 `migration_repair`;项目 143 `clean-run3` 与新项目 `full-chain-final` 主链及 restart 全部纯页面 PASS,目标 404=0 | [remediation](./2026-09-14-controlled-content-canonical-hash-remediation.md)。Wave 3(2026-09-18)已在隔离 docker PG(5436)执行 `TestReconcile_LegacyRepair_PG` 一次并 PASS,工程测试债关闭,见 [test-report](../test-reports/2026-09-18-wave3-test-debt-blindspots-test-report.md) | -| CHAT-HISTORY-REFRESH | 工作流激活后刷新,对话正文被阶段过滤器清空,但分类数量与锚点仍按全量返回 | **PASS** | [test-report](../test-reports/2026-09-13-chat-history-refresh-test-report.md);活验 [live.json](../test-reports/assets/2026-09-15-chat-history-refresh-live/live.json)(项目 6252,window=categories=2,guest 403);代码:`message_scope.go`、`chat_history_auth.go`、goose 00026/00027 | 闲聊刷新已补。发布门禁「激活后文档任务 + 重登/重启」仍开放,不回退本 gap | +| CHAT-HISTORY-REFRESH | 工作流激活后刷新,对话正文被阶段过滤器清空,但分类数量与锚点仍按全量返回 | **PASS** | [test-report](../test-reports/2026-09-13-chat-history-refresh-test-report.md);闲聊 [live.json](../test-reports/assets/2026-09-15-chat-history-refresh-live/live.json)(6252,window=categories=2,guest 403);B3 [gate](../test-reports/2026-09-16-chat-refresh-gate-test-report.md)(6359,activate+task window=4,rebuild 4→4);代码 tip `364ed7f1`:`message_scope.go`、`chat_history_auth.go`、goose 00026/00027;[口径裁定](../ops/short-term/2026-09-22-chat-history-refresh-reconcile.md) | 已修且 B3 ☑。红线仍生效:禁空 stage_key 一律放行;禁 localStorage 掩盖服务端空/错。handoff/remediation 已关闭 | | CHAT-INTENT-STATE | 真实会话被诊断探针污染;只读查询误启动文档写任务;错误动作与编辑状态刷新后丢失 | **PASS** | [audit](../audit/2026-09-13-conversation-intent-runtime-state.md);[test-report](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md);双标签活验项目 **6275** / `sess-p6275-u10`(`live.json` + Docker 截图)。**不**删除 `sess-p143-u9` 历史探针 | [remediation](./2026-09-13-conversation-intent-runtime-state-remediation.md)。Wave 3–4 浏览器门已签;诊断污染消息仍不擅自删除 | | ENV-RESTART-SOURCE | `docker compose restart` 只重启旧镜像,健康检查无法证明合入代码已部署 | **PASS** | `env-service.sh rebuild` + 真实摘要重测 | 集成冒烟统一使用 `dev rebuild` | | DOCREV-RUNTIME-404 | revision-state 404;账本内存丢失;块保存/overlay 无效;agent 假报告 | **PASS** | [Round20 报告](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md);[audit](../audit/2026-09-13-document-revision-runtime-404.md) | 运行时 UI 已闭环。change report 仍为 fallback,不冒充 PI。历史失败目录不删 |