From 11e4d5ff09d0040e4267baa7d8935e8ac4321b2c Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Mon, 21 Sep 2026 18:17:31 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E4=BC=9A=E8=AF=9D=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8D=95=E9=AA=8C=E6=94=B6=E9=80=9A=E8=BF=87?= =?UTF-8?q?=EF=BC=8CBUG-990=20=E6=94=B6=E5=8F=A3=E5=B9=B6=E6=9B=B4?= =?UTF-8?q?=E6=AD=A3=E5=BD=B1=E5=93=8D=E9=9D=A2=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20BUG-991?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 门禁 run 2833 全绿、df329fa9 已部署,987~990 回填修复版本。 归档视图的 UI 入口在 92558ee6 就已删除,BUG-990 的用户现象描述更正; 归档后无法查看与恢复记为 BUG-991,待产品决策。 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0199rbQDTsUbCVw84wc8BTFe --- docs/BUG_HISTORY.md | 44 ++++++++++++++++++++++++++++++-------------- docs/tasks/README.md | 4 ++-- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index a4a10830..e40e313d 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -13070,7 +13070,7 @@ - 防复发:不得用「某列为空」推断会话有没有内容。列表过滤必须带 `session_type` 限定。不得用源码正则代替真实行测试。 - 相关记录:BUG-928、BUG-704 - 复发自:BUG-928(空咨询过滤写成全表 `messages <> '[]'`) -- 修复版本:待本修复合入 staging +- 修复版本:`df329fa9`(staging 已部署,门禁 run 2833 全绿) ## BUG-988 | 侧栏副标题用创建时间,排序用最后活动时间,列表读起来是乱的 @@ -13086,7 +13086,7 @@ - 防复发:显示、排序、分组、游标必须用同一个时间字段(`updated_at`)。`SESSION_LIST_COLUMNS` 不得再含 `created_at`。 - 相关记录:BUG-929、BUG-553 - 复发自:BUG-929(副标题改创建时间后与排序键分叉) -- 修复版本:待本修复合入 staging +- 修复版本:`df329fa9`(staging 已部署,门禁 run 2833 全绿) ## BUG-989 | 点「新建对话」复用旧空会话,第一问之前就落库 @@ -13102,20 +13102,36 @@ - 防复发:第一问之前不得 `POST /api/sessions`。未落库会话不得写入 `?c=`。列表响应不得再带 `draft`。 - 相关记录:BUG-928、BUG-987 - 复发自:BUG-928(延迟落库让步未收口) -- 修复版本:待本修复合入 staging +- 修复版本:`df329fa9`(staging 已部署,门禁 run 2833 全绿) -## BUG-990 | 侧栏切到归档记录后 500 +## BUG-990 | `GET /api/sessions?archived=1` 在自托管 Postgres 上 500 + +- 状态:resolved +- 首次发现:2026-09-21 +- 最近更新:2026-09-21 +- 影响面:`LocalPostgresQueryBuilder.not()`、`GET /api/sessions?archived=1`、归档视图 +- 用户现象:**当前无用户可见现象**——归档视图自 `92558ee6`(2026-08-22)起没有 UI 入口(见 BUG-991),前端不会发出 `archived=1`。发现路径是 BUG-987 新加的真实 Postgres 测试第一次跑到归档分支。接口层面确为 500「聊天记录暂时无法读取」。 +- 触发条件:自托管本地 Postgres 上请求 `?archived=1`。托管 Supabase 不受影响。 +- 根因:兼容层 `not()` 只实现 PostgREST 算子子集 `eq` / `cs`。`applyArchiveFilter(..., true)` 调用 `not("archived_at", "is", null)`,构造期不报错,真跑 SQL 时 throw `unsupported not filter`,被列表路由外层 catch 成 500。该调用自 `a1956deb`(BUG-553)就在,此前没有真实数据库测试走到归档分支。 +- 修复:`not()` 增加 `is` 分支,新 filter kind `isNot`,编译为 `is not null` / `is not true` / `is not false`。不得写成 `<> null`(恒为 NULL,会静默 0 行)。 +- 验证:`local-postgres-not.test.ts`(本机绿);`database-session-list-visibility.test.ts` 归档分支在 Gitea 门禁 run **2833** 转绿(`ok 1238`,3653 条全过、0 红 0 skip),`deploy-staging` run 2835 成功,`/api/health` 的 `deployment.gitCommit` = `df329fa9`。执行方本机 Docker 网段耗尽未跑 `test:db`,见 `BLOCKED.md`。 +- 防复发:兼容层新增算子必须有真实 Postgres 覆盖,不得只加源码正则。 +- 相关记录:BUG-553、BUG-926、BUG-987 +- 复发自:BUG-926(同一兼容层的不同缺口:当时是 `order()` 只留最后一键) +- 修复版本:`df329fa9`(staging 已部署) + +## BUG-991 | 会话归档后没有任何入口能看回来或恢复 - 状态:investigating - 首次发现:2026-09-21 - 最近更新:2026-09-21 -- 影响面:`LocalPostgresQueryBuilder.not()`、`GET /api/sessions?archived=1`、侧栏「归档记录」 -- 用户现象:点侧栏「归档记录」后聊天记录读不出来(500「聊天记录暂时无法读取」)。 -- 触发条件:自托管本地 Postgres 上打开归档视图。托管 Supabase 不受影响。 -- 根因:兼容层 `not()` 只实现 PostgREST 算子子集 `eq` / `cs`。`applyArchiveFilter(..., true)` 调用 `not("archived_at", "is", null)`,构造期不报错,真跑 SQL 时 throw `unsupported not filter`,被列表路由外层 catch 成 500。该调用自 `a1956deb`(BUG-553)就在,此前没有真实数据库测试走到归档分支。 -- 修复:`not()` 增加 `is` 分支,新 filter kind `isNot`,编译为 `is not null` / `is not true` / `is not false`。不得写成 `<> null`(恒为 NULL,会静默 0 行)。 -- 验证:`local-postgres-not.test.ts`;`database-session-list-visibility.test.ts` 归档分支(有 Docker 时)。**本记录在 `test:db` 或门禁该测试转绿前不得标 resolved。** -- 防复发:兼容层新增算子必须有真实 Postgres 覆盖,不得只加源码正则。 -- 相关记录:BUG-553、BUG-926、BUG-987 -- 复发自:BUG-926(同一兼容层的不同缺口:当时是 `order()` 只留最后一键) -- 修复版本:待本修复合入 staging 且门禁该测试转绿 +- 影响面:`app-sidebar.tsx` 会话分组页眉、`SidebarSessionControls.onToggleArchivedView` / `archivedCount`、`toggleArchivedView` +- 用户现象:会话行菜单里可以「归档」,归档后它从侧栏消失;此后没有任何界面能列出归档记录,行菜单里的「恢复」也跟着不可达。除非记得 `?c=` 深链,归档等于单向丢失。 +- 触发条件:在会话行菜单点「归档」。 +- 根因:`92558ee6`(2026-08-22,`fix(web): stack mobile audit tables and restore sidebar hierarchy`)删掉了分组页眉上的 `session-nav-toggle` 按钮(原文案「归档 N」/「返回」),但保留了它背后的整条链路:`onToggleArchivedView`、`archivedCount`、`showingArchived`、`toggleArchivedView()` 与 `GET /api/sessions?archived=1` 全部还在,只是没有调用者。`app-sidebar.tsx` 里两处 `showingArchived ? "归档记录" : …` 的三元条件因此恒取后者。全仓唯一提到 `onToggleArchivedView` 的非类型声明位置是 `use-home-shell-registration.ts` 里提供它的那一行。 +- 修复:待产品决策——恢复入口,或把归档能力整体下线(用户偏好:多余入口宁可删除也不修)。本轮只记录事实。 +- 验证:`grep -rn "ToggleArchivedView" frontend/src` 只有声明与提供方,无渲染调用点;`grep -rn "归档" frontend/src --include=*.tsx` 只剩行菜单文案与分组 aria-label。 +- 防复发:删除某个视图的唯一入口时,必须同时下线其数据链路,或留一条断言入口存在的测试;不得留下"接口活着、界面没有"的半截功能。 +- 相关记录:BUG-990、BUG-553 +- 复发自:无 +- 修复版本:未修复 diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 6c865299..4cf91439 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -152,8 +152,8 @@ | `TASK-consultation-answer-start-anchor-20260917.md` | `PROGRESS-consultation-answer-start-anchor-20260917.md` | 主会话回答落在结尾:`useConversationScrollAnchor` 是贴底跟随,流式期间视口钉在最后一个字,回答开头滚出视口;改为发送后问题钉顶、回答向下长、长出视口显示「跳到最新」、末尾动态留白;产品追加拍板:校正面同一语义(推翻 BUG-041/048 贴底),本轮开头 = 用户行或新助手行。BUG 段 930 起 | 已验收(经修复单) | `worktree/green-harbor-5be3` | | `TASK-consultation-answer-start-anchor-fix-20260917.md` | `PROGRESS-consultation-answer-start-anchor-fix-20260917.md` | 验收修复单:F1 头就是留白行时留白按整视口算(BUG-931);F2 留白只在钉住期间存在(BUG-932);前置:先修 e4e73f56 的两处 TS 错否则门禁不过 | 已验收 | `cc1a8980`(Claude 验收:tsc 0 / lint 0 error / npm test 3457 条 39 红与 11c0028d 逐条一致、新增 2 条绿 / `next build --webpack` 通过、`/` Static、首屏 gzip 591,242(较 09-16 基线 582,800 +1.45%,含会话列表单)/ Chrome 真实布局 S1–S6 全部通过,S6 新助手行距顶 16px 且增高不动,S5 不再写留白);真机六条欠 | | — | `PROGRESS-starter-greeting-20260917.md` | 首页开场语改成 claude.ai 式单行问候:`starter-greeting.ts` 的「称呼 + 追问句」五时段十五条收成三个池子(时段 / 星期 / 回访,按 `variantSelection` 确定性取一条),副标题行与 `.starter-salutation` 下线,h1 降到 `clamp(24px, 2.8vw, 30px)`;追问移到输入框占位符「想聊什么都可以」。产品直接拍板,非 Bug,不占 BUG 号 | 待验收 | `codex/starter-greeting-20260917` | -| `TASK-session-list-rebuild-20260921.md` | `PROGRESS-session-list-rebuild-20260921.md` | **P0 会话列表重建(`e4e73f56` 的返工)**:服务端 `GET /api/sessions` 用 `messages <> '[]'` 排除空咨询,但校正会话的 `messages` 永远是 `[]`(建行写死空数组、创建合同只收空数组、PATCH 忽略、`touch_chat_session_from_rectification_case` 只 bump `updated_at`)→ **全部生时校正会话从侧栏消失**,而客户端 `isListedSidebarSession` 明确放行校正会话,两层规则相反且无跨层对断(BUG-987);同一提交把副标题换成 `created_at`,排序/分组/游标仍是 `updated_at`,列表可见时间不单调(9/18→9/17→9/7→9/16)(BUG-988);BUG-928 让步下来的「复用空会话」不 bump 时间,点新建变成跳回 9/17 的旧草稿(BUG-989)。**产品 09-21 拍板**:D1 副标题改最后活动时间(推翻 BUG-929 该条,其余保留)、D2 收掉 `BLOCKED.md:120` 的让步,第一问前不落库、删复用与 `draft`。T1 不得让步,T3 可拆轮。BUG 段 987 起 | **验收未通过(1 条 P1)** | `e71e4f92`(Claude 验收:T1/T2/T3 实现均正确;tsc 0 / lint 0 error 119 warning 与基线同 / `npm test` 本机 3640 条 34 红与 `f8d65e48` 逐条一致、净增 5 绿 / `next build --webpack` 通过、`/` Static、首屏 gzip 643,115 较基线 −0.027% / page.tsx 1826→1791。**P1:门禁 run 2832 红、staging 未部署**——新加的真实 Postgres 测试在有 Docker 的门禁机上跑出 `unsupported not filter`,兼容层 `not()` 不支持 `is` 算子,归档分支炸。修复单 `TASK-session-list-rebuild-fix-20260921.md`) | -| `TASK-session-list-rebuild-fix-20260921.md` | `PROGRESS-session-list-rebuild-fix-20260921.md` | **验收修复单(挡着三条修复上线)**:本地 PG 兼容层 `LocalPostgresQueryBuilder.not()` 只认 `eq` / `cs` 两个算子,`not("archived_at","is",null)` 直接 throw → `GET /api/sessions?archived=1` 落外层 catch 回 500,**侧栏「归档记录」自 `a1956deb`(09-06,BUG-553)起一直打不开**,两周无人发现是因为只有源码正则合同看着它;本轮新加的真实 Postgres 测试第一次真跑到这条路径,把它照出来,于是门禁 run 2832 红、`e71e4f92` 没部署。**决策**:在兼容层补 `is not null / is not true / is not false`,不得反过来改调用方绕开,不得删改测试断言让门禁变绿。与 BUG-926 的 `order()` 缺口同类。BUG 段 990 起 | 待验收 | `codex/session-list-rebuild-fix-20260921` | +| `TASK-session-list-rebuild-20260921.md` | `PROGRESS-session-list-rebuild-20260921.md` | **P0 会话列表重建(`e4e73f56` 的返工)**:服务端 `GET /api/sessions` 用 `messages <> '[]'` 排除空咨询,但校正会话的 `messages` 永远是 `[]`(建行写死空数组、创建合同只收空数组、PATCH 忽略、`touch_chat_session_from_rectification_case` 只 bump `updated_at`)→ **全部生时校正会话从侧栏消失**,而客户端 `isListedSidebarSession` 明确放行校正会话,两层规则相反且无跨层对断(BUG-987);同一提交把副标题换成 `created_at`,排序/分组/游标仍是 `updated_at`,列表可见时间不单调(9/18→9/17→9/7→9/16)(BUG-988);BUG-928 让步下来的「复用空会话」不 bump 时间,点新建变成跳回 9/17 的旧草稿(BUG-989)。**产品 09-21 拍板**:D1 副标题改最后活动时间(推翻 BUG-929 该条,其余保留)、D2 收掉 `BLOCKED.md:120` 的让步,第一问前不落库、删复用与 `draft`。T1 不得让步,T3 可拆轮。BUG 段 987 起 | **已验收**(经修复单) | `e71e4f92`(Claude 验收:T1/T2/T3 实现均正确;tsc 0 / lint 0 error 119 warning 与基线同 / `npm test` 本机 3640 条 34 红与 `f8d65e48` 逐条一致、净增 5 绿 / `next build --webpack` 通过、`/` Static、首屏 gzip 643,115 较基线 −0.027% / page.tsx 1826→1791。**P1:门禁 run 2832 红、staging 未部署**——新加的真实 Postgres 测试在有 Docker 的门禁机上跑出 `unsupported not filter`,兼容层 `not()` 不支持 `is` 算子,归档分支炸。修复单 `TASK-session-list-rebuild-fix-20260921.md` 已验收通过,`df329fa9` 已部署) | +| `TASK-session-list-rebuild-fix-20260921.md` | `PROGRESS-session-list-rebuild-fix-20260921.md` | **验收修复单(挡着三条修复上线)**:本地 PG 兼容层 `LocalPostgresQueryBuilder.not()` 只认 `eq` / `cs` 两个算子,`not("archived_at","is",null)` 直接 throw → `GET /api/sessions?archived=1` 落外层 catch 回 500,**侧栏「归档记录」自 `a1956deb`(09-06,BUG-553)起一直打不开**,两周无人发现是因为只有源码正则合同看着它;本轮新加的真实 Postgres 测试第一次真跑到这条路径,把它照出来,于是门禁 run 2832 红、`e71e4f92` 没部署。**决策**:在兼容层补 `is not null / is not true / is not false`,不得反过来改调用方绕开,不得删改测试断言让门禁变绿。与 BUG-926 的 `order()` 缺口同类。BUG 段 990 起 | **已验收通过** | `df329fa9`(Claude 验收:`not()` 增 `isNot` kind,统一走新的 `compileUnaryIsClause` 编译 `is [not] null/true/false`,非法取值仍 throw;`filterClause` 是唯一消费者、已覆盖,未落进兜底分支。**门禁 run 2833 全绿:3653 条 / 3653 过 / 0 红 / 0 skip**,`ok 1238` 即那条真实 Postgres 归档测试;migrate 2834、deploy 2835 成功,`/api/health` 的 `deployment.gitCommit` = `df329fa9`。本机复跑:tsc 0 / lint 0 error 119 warning 未增 / `npm test` 用例名逐条 diff 较 `e71e4f92` **恰好 +2 无删除**、失败清单完全一致 / `next build --webpack` 通过、`/` Static、首屏 gzip 643,116(+1 B)。**顺带查出 BUG-991**:归档视图的 UI 入口在 `92558ee6`(08-22)就被删了,`onToggleArchivedView` 全仓无调用点 → BUG-990 原描述「用户点归档记录后 500」不成立(接口层 500 属实,用户碰不到),已在 Bug 历史更正;归档后看不回来也恢复不了是真问题,待产品决策) | ### 个人报告