docs(tasks): accept e2f4b55c (BUG-542/551-556); session title guard fix brief (BUG-557)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
This commit is contained in:
@@ -44,3 +44,16 @@ Node 22 mock 契约:子进程 `mock.module(..., { namedExports })`(BUG-514
|
||||
## 遗留
|
||||
|
||||
未做浏览器真人走查。部署窗口的短暂 503 仍会出现,只是说法不再误导成环境变量丢失。未跑全量 `npm run lint` / `npm test`(任务书验收是 tsc + lint 0 error + 本单测试;改动文件 eslint 已 0 error)。
|
||||
|
||||
## 验收(Claude,2026-09-06,对照 `TASK-api-not-configured-mislabel-20260904.md`)
|
||||
|
||||
共用门禁(`origin/staging` @ `e2f4b55c`,含五单全部提交):`tsc --noEmit` 0 错;`npm run lint` 0 error / 79 warning(全部既有);`npx tsx --test tests/*.test.ts` 2770 项 / pass 2729 / fail 29 / skipped 12——29 条失败全为环境缺口(25 条 Docker / rsync / pyyaml 缺失的库测与部署套件;2 条 `--experimental-test-module-mocks` 子进程在本机 Node 20 下解析不到 `@/` 别名,CI 为 Node 22;2 条 `beam-avatar` / `chat-composer-queue` 渲染用例因验收工作树里一个多余的 `node_modules/node_modules` 软链造成双份 React,删链后单独重跑通过);默认 `npm run build`(Turbopack)退出 0、`/` 为 `○ Static`、产物无 `/membership` 页;首屏 JS gzip-9(预渲染 `index.html` 引用脚本去重求和,与 09-02 口径一致)`d2a209d3` 519,437 B → `e2f4b55c` 522,617 B,**+3,180 B / +0.61%**,五单合计在 ±2% 内。执行方进度里「`next build --webpack` 停在 `dossierResponse` 导出类型」一事:`dc6598d7` 已去掉该 `export`,本次默认构建不再出现。
|
||||
|
||||
| 项 | 结论 | 依据 |
|
||||
| --- | --- | --- |
|
||||
| 5.1 共享 helper,只在 `isSupabaseConfigurationError` 时说「服务尚未配置」 | 通过 | `lib/api/service-unavailable.ts::jsonForSupabaseSetupFailure`;其余异常 503 `service_unavailable` + `console.error(routeName, errorName)`,不打印 message |
|
||||
| 5.2 16 处路由替换、无遗漏 | 通过 | `grep -rn "服务尚未配置" frontend/src` 只命中 helper |
|
||||
| 5.3 测试 `tests/api-service-unavailable-20260904.test.ts` | 环境缺口 | 4 条中 2 条走 `--experimental-test-module-mocks` 子进程,本机 Node 20 解析不到 `@/`(与既有 `report export` 用例同一模式);CI Node 22 应绿,以门禁结果为准 |
|
||||
| 5.4 BUG-542 记录、CHANGELOG | 通过 | `docs/BUG_HISTORY.md` BUG-542 |
|
||||
|
||||
**结论:通过**(2 条测试留 CI 复核)。修复 SHA `5483649b`。
|
||||
|
||||
@@ -37,3 +37,17 @@
|
||||
| `tests/class-name-definition-contract.test.ts` | 3/3 |
|
||||
| `page.tsx` | 2040 行 |
|
||||
| `npm run build -- --webpack` | 编译通过;随后在既有 `dossierResponse` 路由导出类型上失败,与本次无关 |
|
||||
|
||||
## 验收(Claude,2026-09-06,对照 `TASK-composer-live-input-and-stop-20260906.md`)
|
||||
|
||||
共用门禁(`origin/staging` @ `e2f4b55c`,含五单全部提交):`tsc --noEmit` 0 错;`npm run lint` 0 error / 79 warning(全部既有);`npx tsx --test tests/*.test.ts` 2770 项 / pass 2729 / fail 29 / skipped 12——29 条失败全为环境缺口(25 条 Docker / rsync / pyyaml 缺失的库测与部署套件;2 条 `--experimental-test-module-mocks` 子进程在本机 Node 20 下解析不到 `@/` 别名,CI 为 Node 22;2 条 `beam-avatar` / `chat-composer-queue` 渲染用例因验收工作树里一个多余的 `node_modules/node_modules` 软链造成双份 React,删链后单独重跑通过);默认 `npm run build`(Turbopack)退出 0、`/` 为 `○ Static`、产物无 `/membership` 页;首屏 JS gzip-9(预渲染 `index.html` 引用脚本去重求和,与 09-02 口径一致)`d2a209d3` 519,437 B → `e2f4b55c` 522,617 B,**+3,180 B / +0.61%**,五单合计在 ±2% 内。执行方进度里「`next build --webpack` 停在 `dossierResponse` 导出类型」一事:`dc6598d7` 已去掉该 `export`,本次默认构建不再出现。
|
||||
|
||||
| 项 | 结论 | 依据 |
|
||||
| --- | --- | --- |
|
||||
| 5.1 输入框不再随生成禁用;生成中回车进排队卡,结束后自动发出 / 失败放回 | 通过 | `lib/queued-draft.ts::queuedDraftSettleAction`(completed / succeeded → 发送,其余 → 放回);`page.tsx` `inputDisabled` 只剩结构性条件,`submitBlocked` 含 `Boolean(queuedDraft)`;`useConsultationRun` 开跑时 `setReplyOutcome(null)`,结算 effect 不会用上一轮结果误发 |
|
||||
| 5.2 校正面停止改中性态、选择题 / 采用等待中停止有效 | 通过 | `stopped: true` 气泡、`isAbortError`、choice / adopt fetch 挂 `runAbort` 的 `AbortController`,`rectification-agentic-entry` 新增 abort 用例 |
|
||||
| 5.3 `page.tsx` 不增行 | 通过 | 2041 → 2040(本单)→ 1976(BUG-554 后) |
|
||||
| 5.4 测试 / DESIGN / VOICE / BUG-551、552 | 通过 | `chat-composer-queue.test.ts` 4 条本机通过(删双份 React 软链后) |
|
||||
| 备注(不阻塞) | — | `useConsultationRun` 现在内部含 `useQueuedMessage` + `useEffect`,偏离 AGENTS §6「参数式 hook 内部 0 个 React hook」;任务书 §5 允许「或按仓库既定模式」,本次不追;下次改该 hook 时留意 |
|
||||
|
||||
**结论:通过**。修复 SHA `055b7adc`。真实环境走查见 `docs/testing/composer-live-input-and-stop-20260906.md`。
|
||||
|
||||
@@ -59,3 +59,21 @@
|
||||
- 溢出重试只包住 `agent.stream()` 抛错;流开始之后供应商才报超窗时不会第二次缩窗(咨询公共事件不能发 `attempt.reset`)。
|
||||
- 摘要失败只 `console.warn("session context summary failed", error)`,不打印摘要正文。
|
||||
- `costMicrousd` 仍按全价输入单价。
|
||||
|
||||
## 验收(Claude,2026-09-06,对照 `TASK-consultation-context-and-cache-20260906.md`)
|
||||
|
||||
共用门禁见 `PROGRESS-session-list-title-and-order-20260906.md` 验收段(`e2f4b55c`:tsc 0 错、lint 0 error、2770 项测试 29 条环境失败、`next build` `/` Static、首屏 gzip +0.61%)。
|
||||
|
||||
| 项 | 结论 | 依据 |
|
||||
| --- | --- | --- |
|
||||
| 5.1 迁移 `20260906010000_chat_session_context_summary.sql`(`context_summary jsonb null` + 列级 grant) | 通过(`test:db` 环境缺口) | 本机无 Docker;执行方 `BLOCKED.md` 已记 Docker 地址池耗尽;**部署前必须先跑 Migrate Staging Database** |
|
||||
| 5.1 历史 = 摘要之后 append-only 尾巴;单条 12,000 + 省略标记;按 `context_window` 预算 `clamp((cw−60k)×1.5, 4k, 40k)` 从最旧丢整条;null → 128k | 通过 | `consultation-session-history.ts::consultationHistoryWindow / historyBudgetChars / clipConsultationHistoryText`;`model-catalog.ts` 现读 `v.context_window` |
|
||||
| 5.1 检查点摘要:尾巴 >16,000 字才触发、最后一对不进摘要、`complete_consultation_response` 成功后异步、不扣点、ref 计时器 15 s、默认模型、正则清洗、乐观并发 | 通过 | `session-context-summary.ts`;`checkpointConsultationContext` 的 update 带 `context_summary->>updatedAt = seen` / `is null` 守卫;`messages` 数组只追加不删(RPC 全部核过),`throughMessageIndex` 稳定 |
|
||||
| 5.1 摘要放最后一条用户消息、时间行之后、问题之前 | 通过 | `consultationUserTurnContent`;三条路径(agentic / general / legacy)同一函数 |
|
||||
| 5.1 溢出识别 + 同请求一次降级重试 | 通过(有边界) | `isContextOverflowError` 覆盖 OpenAI / Anthropic 文案与 400;`streamWithOverflowRetry` 只包 `agent.stream()` 抛错,流开始后的供应商报错不再缩窗——执行方已在「收尾限制」写明,接受 |
|
||||
| 5.2 后台缓存可见 | 通过 | `api/admin/usage/aggregate` 按 `actual_model_id` × 7/30 天给 `runsWithCache / hitRate / readTokens / writeTokens / noCacheTokens / cacheShare`;列表 `cacheReadTokens` |
|
||||
| 5.3 Anthropic 最后一条历史加第二断点 | 通过 | `agent-generation-settings.ts::cachedHistoryMessage` 仅 anthropic 生效 |
|
||||
| 5.4 Full-spectrum + Event judgment skeleton 进系统块、工具结果只剩领域段 | 通过 | `skill-binding.ts` `<jyotish-shared-method>`(+6,446 B);`consultation-methodology.ts::sharedConsultationMethodMarkdown`;9 段节选未回退 |
|
||||
| 5.5 BUG-555 / 556、CHANGELOG、testing 清单 | 通过 | — |
|
||||
|
||||
**结论:通过**(`test:db` 为环境缺口)。修复 SHA `bf8ad0d1`。部署顺序:先 Migrate Staging Database(本迁移 + `bab07187` 的 `5010000_personal_report_longform_appendices.sql`),再 deploy,再核 `/api/health`。
|
||||
|
||||
@@ -50,3 +50,20 @@
|
||||
| `page.tsx` | 2035 行(上限 2041) |
|
||||
| `npm run build -- --webpack` | webpack 编译通过;类型检查仍停在既有 `dossierResponse` 路由导出(`api/rectification/cases/[caseId]`),与本单无关。本单曾误把 `metadataUpdateValues` 从 sessions `[id]` 路由再导出,已撤回。 |
|
||||
| 全量 `npm test`(含 `database-*`) | 本机 Docker 库测多项 300s 超时 / 权限负例 ERROR,与本单无关;未当作本单回归。 |
|
||||
|
||||
## 验收(Claude,2026-09-06,对照 `TASK-session-list-title-and-order-20260906.md`)
|
||||
|
||||
共用门禁(`origin/staging` @ `e2f4b55c`,含五单全部提交):`tsc --noEmit` 0 错;`npm run lint` 0 error / 79 warning(全部既有);`npx tsx --test tests/*.test.ts` 2770 项 / pass 2729 / fail 29 / skipped 12——29 条失败全为环境缺口(25 条 Docker / rsync / pyyaml 缺失的库测与部署套件;2 条 `--experimental-test-module-mocks` 子进程在本机 Node 20 下解析不到 `@/` 别名,CI 为 Node 22;2 条 `beam-avatar` / `chat-composer-queue` 渲染用例因验收工作树里一个多余的 `node_modules/node_modules` 软链造成双份 React,删链后单独重跑通过);默认 `npm run build`(Turbopack)退出 0、`/` 为 `○ Static`、产物无 `/membership` 页;首屏 JS gzip-9(预渲染 `index.html` 引用脚本去重求和,与 09-02 口径一致)`d2a209d3` 519,437 B → `e2f4b55c` 522,617 B,**+3,180 B / +0.61%**,五单合计在 ±2% 内。执行方进度里「`next build --webpack` 停在 `dossierResponse` 导出类型」一事:`dc6598d7` 已去掉该 `export`,本次默认构建不再出现。
|
||||
|
||||
| 项 | 结论 | 依据 |
|
||||
| --- | --- | --- |
|
||||
| 5.1 起名 Agent:ref 计时器 8 s、30 token、清洗 6–14 汉字 / 拒换行 / 拒生日形态 | 通过 | `lib/session-title-agent.ts`、`lib/session-title.ts::sanitizeSessionTitle` |
|
||||
| 5.1 只在首轮、非校正、非日期式标题时起名;与主回答并行、`session.title` 流事件 | 通过 | `shouldGenerateSessionTitle`;`use-consultation-run.ts` `streamedTitle ?? reply.title` |
|
||||
| 5.1 **服务端守卫写库** | **未通过(P1)** | `api/consult/route.ts` L693 的 `expectedTitle` 取自 RPC 之前的 select;L531 `append_consultation_question` 已把空 / 「新对话」标题改写成 `left(question,14)‖'…'`(迁移 `20260901010000` L84–90);L710 `.eq("title", expectedTitle)` 因此对新会话恒匹配 0 行且无报错——服务端从不落库模型标题,只靠客户端结算时 PATCH。用户中途刷新 / 换设备时 `status` 路由回读的是问题截断标题。无测试覆盖此守卫。修复单 `TASK-session-title-guard-fix-20260906.md`(BUG-557) |
|
||||
| 5.2 侧栏去「资料名 · 」前缀、他人资料小字副标题 | 通过 | `home-profile.ts::sessionSidebarTitle` / `sessionSidebarSubtitle` |
|
||||
| 5.3 排序:置顶 + `updatedAt` 倒序;元数据 PATCH 不再推进 `updated_at`;客户端改名不再 `timestamp()` | 通过 | `session-metadata-update.ts` 只展开 patch 字段;`use-session-management.ts` 无 `updatedAt: timestamp()` |
|
||||
| 5.4 今天 / 昨天 / 7 天 / 30 天 / 更早分组,收藏不分组 | 通过 | `lib/session-groups.ts::groupSessionsByRecency` |
|
||||
| 5.5 游标分页 40 条、置顶首页全量、`archived=1`、滚到底静默续取 | 通过 | `api/sessions/route.ts`(`limit+1` 探测 `nextCursor`)、`app-sidebar.tsx` `IntersectionObserver`,无 spinner / 「加载更多」文案 |
|
||||
| 5.6 BUG-553、CHANGELOG、testing 清单 | 通过 | — |
|
||||
|
||||
**结论:未通过(1 项 P1,其余通过)**。修复 SHA `a1956deb`;P1 修复单 `TASK-session-title-guard-fix-20260906.md`。
|
||||
|
||||
@@ -72,3 +72,18 @@ Next.js 16 typed routes 不允许 `route.ts` 额外 export。`dossierResponse`
|
||||
分支相对当前 `origin/staging` 落后 2 个提交(BUG-555/556)。未在脏树上合并,避免和本单的 `CHANGELOG` / `BUG_HISTORY` 撞车。
|
||||
|
||||
浏览器走查见 `docs/testing/settings-dialog-and-billing-pane-20260906.md`。本机未起登录会话,真实四分区切换留给 staging 验收。
|
||||
|
||||
## 验收(Claude,2026-09-06,对照 `TASK-settings-dialog-and-billing-pane-20260906.md`)
|
||||
|
||||
共用门禁见 `PROGRESS-session-list-title-and-order-20260906.md` 验收段(`e2f4b55c`:tsc 0 错、lint 0 error、2770 项测试 29 条环境失败、`next build` `/` Static、首屏 gzip +0.61%)。
|
||||
|
||||
| 项 | 结论 | 依据 |
|
||||
| --- | --- | --- |
|
||||
| 5.1 弹窗壳固定尺寸 + 四分区 | 通过 | `.settings-modal { width: min(100vw − 32px, 880px); height: min(84dvh, 640px) }`;`chart-library-modal` / `profile-modal` 已无;导航 个人资料 → 星盘资料 → 账户与点数 → 通用设置 |
|
||||
| 5.2 个人资料搬出 `page.tsx`,无「管理星盘资料」 | 通过 | `profile-panel.tsx`;`page.tsx` 2035 → 1976 行(净减 59 ≥ 40) |
|
||||
| 5.3 星盘资料列表 → 详情 | 通过 | `chart-library-panel.tsx` 内部视图 `list / self / other / add`,默认列表,无无条件 `<form` |
|
||||
| 5.4 「账户与点数」入弹窗;删 `/membership` 与 `/membership/orders`;307 重定向;七处入口改回调;`/` 不用 `useSearchParams` 保持 Static | 通过 | `src/app/membership` 已删;`next.config.ts` 两条 `redirects`;`git grep "/membership" frontend/src` 只剩 `next.config.ts`;`settings-url.ts` 用 `window.location` 解析后 `replaceState` 抹参 |
|
||||
| 5.4 测试迁移(26 条进 `billing-panel.test.ts`)、`settings-url.test.ts`、`chat-navigation-a11y` 三栏表、Python `app_routes` 去掉两条 | 通过 | 三栏表完整;`tests/test_api_server_security.py` 已去 `membership` / `membership/orders` |
|
||||
| 5.5 BUG-554、CHANGELOG、DESIGN、VOICE | 通过 | — |
|
||||
|
||||
**结论:通过**。修复 SHA `dc6598d7`。四分区真实切换、移动端弹窗、`/membership` 深链回落留 `docs/testing/settings-dialog-and-billing-pane-20260906.md` 真人走查。
|
||||
|
||||
@@ -55,12 +55,13 @@
|
||||
| — | `PROGRESS-rectification-family-collect-continue-20260905.md` | 家人答「没有」后直接给结果,未继续收能区分分钟的经历 | 已由 cd704a92 修正并验收通过 | `codex/rectification-quality-probe-dedupe-20260904`(BUG-546) |
|
||||
| `TASK-rectification-family-collect-continue-fix-20260905.md` | `PROGRESS-rectification-family-collect-continue-20260905.md` | `998406ce` 修复单:家人之后的 dated 补采集无条件抢在现成区分卡之前(choice-card A/B 卡用例回归),另两条顺序断言缺三栏说明 | 已验收通过(浏览器走查欠) | `cd704a92`(BUG-547) |
|
||||
| `TASK-rectification-probe-answer-covers-domain-20260905.md` | `PROGRESS-rectification-probe-answer-covers-domain-20260905.md` | 区分卡答 A/B 后紧接着又问同领域"哪年…"采集题:点选答案只进推断层不写账本,计划层领域覆盖只看账本;改为 yes/weak_yes 视为该领域采集已覆盖(不写账本、不动门) | 待验收 | `988d97ae`(BUG-549) |
|
||||
| `TASK-composer-live-input-and-stop-20260906.md` | `PROGRESS-composer-live-input-and-stop-20260906.md` | 生成中输入框整个禁用致焦点丢失、回车丢消息(改为永不禁用 + 排队发送);生时校正停止呈现为红色告警且选择题等待中停止无效(改为中性停止态、所有 fetch 挂 abort) | 待执行 | `codex/composer-live-input-and-stop-20260906`(BUG-551、552) |
|
||||
| `TASK-session-list-title-and-order-20260906.md` | `PROGRESS-session-list-title-and-order-20260906.md` | 历史对话标题改为首轮模型总结(一次、不扣点数、校正/今日运势保持日期标题)、侧栏去资料前缀;排序只按置顶排且元数据 PATCH 推进 `updated_at`(改为置顶 + 活动时间,改名/收藏/换模型不动顺序);历史区加 今天/昨天/7天/30天/更早 分组;列表按游标分页(每页 40、置顶首页全量、滚到底静默续取) | 待执行(串行:在 composer 单之后) | `codex/session-list-title-and-order-20260906`(BUG-553) |
|
||||
| `TASK-settings-dialog-and-billing-pane-20260906.md` | `PROGRESS-settings-dialog-and-billing-pane-20260906.md` | 设置弹窗尺寸随分区跳变、星盘资料格无条件铺开整张添加表单(改为固定尺寸四分区、列表→详情);「账户与点数」成为弹窗分区,删除 `/membership` 与 `/membership/orders` 页面并重定向,七处入口改回调 | 待验收 | `codex/settings-dialog-and-billing-pane-20260906`(BUG-554) |
|
||||
| `TASK-consultation-context-and-cache-20260906.md` | `PROGRESS-consultation-context-and-cache-20260906.md` | 普通对话历史只取每条前 4,000 字(报告结论被砍、无标记)、历史窗口不看模型 `context_window`、无溢出识别;改为检查点式会话摘要 + append-only 尾巴 + 按模型预算 + 一次降级重试;Anthropic 历史断点;共享方法段进系统块;后台用量页显示缓存命中率 | 待执行(串行:在会话列表单之后;动表需迁移) | `codex/consultation-context-and-cache-20260906`(BUG-555/556) |
|
||||
| `TASK-composer-live-input-and-stop-20260906.md` | `PROGRESS-composer-live-input-and-stop-20260906.md` | 生成中输入框整个禁用致焦点丢失、回车丢消息(改为永不禁用 + 排队发送);生时校正停止呈现为红色告警且选择题等待中停止无效(改为中性停止态、所有 fetch 挂 abort) | 已验收 | `055b7adc`(BUG-551/552);验收段见 PROGRESS |
|
||||
| `TASK-session-list-title-and-order-20260906.md` | `PROGRESS-session-list-title-and-order-20260906.md` | 历史对话标题改为首轮模型总结(一次、不扣点数、校正/今日运势保持日期标题)、侧栏去资料前缀;排序只按置顶排且元数据 PATCH 推进 `updated_at`(改为置顶 + 活动时间,改名/收藏/换模型不动顺序);历史区加 今天/昨天/7天/30天/更早 分组;列表按游标分页(每页 40、置顶首页全量、滚到底静默续取) | 已验收(1 项 P1) | `a1956deb`(BUG-553);服务端标题守卫恒不命中,修复单 `TASK-session-title-guard-fix-20260906.md` |
|
||||
| `TASK-settings-dialog-and-billing-pane-20260906.md` | `PROGRESS-settings-dialog-and-billing-pane-20260906.md` | 设置弹窗尺寸随分区跳变、星盘资料格无条件铺开整张添加表单(改为固定尺寸四分区、列表→详情);「账户与点数」成为弹窗分区,删除 `/membership` 与 `/membership/orders` 页面并重定向,七处入口改回调 | 已验收 | `dc6598d7`(BUG-554);真人走查欠 |
|
||||
| `TASK-consultation-context-and-cache-20260906.md` | `PROGRESS-consultation-context-and-cache-20260906.md` | 普通对话历史只取每条前 4,000 字(报告结论被砍、无标记)、历史窗口不看模型 `context_window`、无溢出识别;改为检查点式会话摘要 + append-only 尾巴 + 按模型预算 + 一次降级重试;Anthropic 历史断点;共享方法段进系统块;后台用量页显示缓存命中率 | 已验收 | `bf8ad0d1`(BUG-555/556);`test:db` 环境缺口;部署前先 Migrate Staging Database |
|
||||
| `TASK-session-title-guard-fix-20260906.md` | `PROGRESS-session-title-guard-fix-20260906.md` | BUG-553 修复单:`consult/route.ts` 标题守卫比较的是 RPC 前快照,`append_consultation_question` 已改写标题,守卫恒 0 行,模型标题只靠客户端 PATCH 落库 | 待执行 | `codex/session-title-guard-fix-20260906`(BUG-557) |
|
||||
| `TASK-rectification-collect-vs-offer-consistency-20260905.md` | `PROGRESS-rectification-collect-vs-offer-consistency-20260905.md` | 带年份采集没问完就出采用卡 + 报告,同一轮又被搬家采集题把卡挤掉:决策层判 `adopt_representative` 而计划层仍有 dated 采集(BUG-546 只修了一半);改为剩余采集未完保持 `collect_evidence`,出牌轮才出卡写报告 | 已验收通过 `ca4e2408`(2026-09-05;staging 部署仍停在 `afd14948`,`deploy-staging` 自 `c295b853` 起连续失败,先解决 `bab07187` 的待迁移) | `codex/rectification-collect-vs-offer-consistency-20260905`(BUG-550) |
|
||||
| `TASK-api-not-configured-mislabel-20260904.md` | `PROGRESS-api-not-configured-mislabel-20260904.md` | 16 处路由把数据库瞬断(部署切换窗口)兜底翻译成 503「服务尚未配置」;改为仅配置错误用该文案,其余 `service_unavailable`,收敛为共享 helper | 待验收 | `codex/api-not-configured-mislabel-20260904`(BUG-542) |
|
||||
| `TASK-api-not-configured-mislabel-20260904.md` | `PROGRESS-api-not-configured-mislabel-20260904.md` | 16 处路由把数据库瞬断(部署切换窗口)兜底翻译成 503「服务尚未配置」;改为仅配置错误用该文案,其余 `service_unavailable`,收敛为共享 helper | 已验收 | `5483649b`(BUG-542);2 条子进程测试留 CI Node 22 复核 |
|
||||
| `TASK-rectification-ux-20260902.md` | `PROGRESS-rectification-ux-20260903.md` | 会话面空白假死与交互摩擦 | 已验收 | `d159f08e`(09-03 在新基线重做后合入,BUG-505~509) |
|
||||
|
||||
### 聊天主链路与首页
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# TASK · 会话标题守卫写库恒不命中(BUG-553 修复单)(2026-09-06)
|
||||
|
||||
- 基线:`origin/staging` @ `e2f4b55c`(含 BUG-553 实现 `a1956deb`)
|
||||
- 分支:`codex/session-title-guard-fix-20260906`
|
||||
- 执行方:coding agent;验收:Claude
|
||||
- 涉及文件:`frontend/src/app/api/consult/route.ts`(只改标题守卫段)、`frontend/tests/application-billing-contract.test.ts` 或新 `frontend/tests/session-title-persist-contract.test.ts`;不动迁移、不动客户端、不动 `session-title-agent.ts`
|
||||
- BUG 编号起点:**BUG-557**(开工时 `grep -o "^## BUG-5[0-9][0-9]" docs/BUG_HISTORY.md | tail -1` 复核)
|
||||
- 串行:与 `TASK-consultation-context-and-cache` 的 `route.ts` 改动已合入,无并行冲突
|
||||
|
||||
## 1. 事故实证(代码验收,未上线)
|
||||
|
||||
`frontend/src/app/api/consult/route.ts`:
|
||||
|
||||
| 行 | 事实 |
|
||||
| --- | --- |
|
||||
| ~L282 | `chatSession` select 读到会话标题(新会话为空或「新对话」) |
|
||||
| L531 | `accounting.rpc("append_consultation_question")` —— 迁移 `20260901010000_append_consultation_question.sql` L84–90 在标题为空 / 「新对话」时把标题改写成 `left(question,14) || '…'`(≤14 字时为整句) |
|
||||
| L693 | `const expectedTitle = chatSession.title`(RPC **之前**的值) |
|
||||
| L710 | `update({ title }).eq("id").eq("user_id").eq("title", expectedTitle)` |
|
||||
|
||||
对任何新会话,L710 的 `title = expectedTitle` 都比不上 L531 已改写的值,更新影响 0 行、Supabase 不报错、`console.warn` 不触发。模型标题只在客户端结算时通过 `persistSession` 的 PATCH 落库;用户中途刷新、关标签、换设备时 `api/consult/status` 回读的是问题截断标题,起名白做。`tests/session-title-agent.test.ts` 与 `application-billing-contract.test.ts` 都没有断言这条守卫会命中。
|
||||
|
||||
## 2. 根因
|
||||
|
||||
任务书 §3 决策 3「只在标题仍等于本轮开始时读到的值时更新」写的是「本轮开始」,而本轮真正改标题的是 RPC;执行方按字面取了 RPC 前的快照。守卫本身设计没错,取值时机错。
|
||||
|
||||
## 3. 决策记录
|
||||
|
||||
1. 起名触发条件(`shouldGenerateSessionTitle(expectedTitle-before-RPC, storedHistory)`)**不变**:仍用 RPC 之前的标题判断「是否自动派生」,否则 ≤14 字的问题会被当成用户手改标题而不起名。
|
||||
2. 守卫的比较值改为 **RPC 之后的真实标题**:RPC 成功后再 `select("title")` 一次(一次主键查询,可接受),把该值作为 `expectedTitle` 传给守卫。不用 TS 重算 SQL 规则(`safeQuestionTitle` 与 SQL 的标点处理不同,重算会再次错配)。
|
||||
3. 用户中途改名以用户为准这条语义保持:守卫仍是 `.eq("title", <RPC 后标题>)`。
|
||||
4. 守卫更新要 `.select("id")` 回读影响行数,0 行时 `console.warn("session title guard missed")`,不再静默。
|
||||
|
||||
## 4. 硬红线
|
||||
|
||||
- 不改 RPC、不改迁移、不改客户端 `use-consultation-run.ts`。
|
||||
- 不得把守卫放宽成无条件写入。
|
||||
- 不得为测试重写路由结构;用现有 `application-billing-contract.test.ts` 的源码合同方式或 mock Supabase 链的方式二选一。
|
||||
|
||||
## 5. 任务分解
|
||||
|
||||
### 5.1 守卫取 RPC 后标题
|
||||
- `route.ts`:`appendedQuestion` 成功后 `const { data: titleRow } = await supabase.from("chat_sessions").select("title").eq("id", sessionId).eq("user_id", userId).maybeSingle()`;`shouldGenerateSessionTitle` 仍用 RPC 前标题;守卫 `.eq("title", titleRow?.title ?? expectedTitle)`;更新后 `.select("id")`,长度 0 → `console.warn`。
|
||||
- 验收:测试——模拟 RPC 前标题「新对话」、RPC 后标题「问题前 14 字…」、模型标题「X」:断言 update 链的 `eq("title", …)` 收到的是 RPC 后标题;模拟用户中途把标题改成「我的标题」(回读值与守卫值不等)→ 更新 0 行且 `console.warn` 被调用一次、返回的流事件仍是 `session.title`。
|
||||
|
||||
### 5.2 记录
|
||||
- `docs/BUG_HISTORY.md` BUG-557(关联 BUG-553;说明为何 a1956deb 的测试没拦住:无守卫命中断言);`CHANGELOG.md` 一条;`docs/tasks/PROGRESS-session-title-guard-fix-20260906.md`;`docs/testing/session-list-title-and-order-20260906.md` 补一条「首轮生成中刷新页面,回来后标题仍是模型标题」。
|
||||
|
||||
## 6. 让步顺序
|
||||
|
||||
5.1 不可拆;5.2 不可省。
|
||||
|
||||
## 7. 开工前置命令
|
||||
|
||||
```bash
|
||||
git fetch origin --prune
|
||||
git worktree add -b codex/session-title-guard-fix-20260906 .worktrees/session-title-guard-fix-20260906 origin/staging
|
||||
cd .worktrees/session-title-guard-fix-20260906/frontend
|
||||
ln -s /workspace/Jyotisha/frontend/node_modules node_modules # 注意:不要在已有 node_modules 的目录里再建,会产生 node_modules/node_modules 双份 React
|
||||
npx tsx --test tests/session-title-agent.test.ts tests/application-billing-contract.test.ts 2>&1 | grep -E "^# (tests|pass|fail)|^not ok"
|
||||
```
|
||||
|
||||
收尾同一条命令 fail=0,再 `tsc --noEmit`、`npm run lint`。
|
||||
Reference in New Issue
Block a user