fix(chat): make cloud the only truth for charts, synastry, and pin/archive
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled

Local fallbacks were creating fake saves and resurrecting deleted rows.
Pin and archive now live on chat_sessions so they follow the account.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-01 21:38:21 +08:00
parent 31c7b48261
commit ce6a8a7e72
16 changed files with 390 additions and 153 deletions
+20
View File
@@ -1104,3 +1104,23 @@
- `./node_modules/.bin/tsc --noEmit` 通过。
- `npm test`**2424 通过 / fail=0 / skipped=0**(含数据库测试;本轮未改库)。
- 实测:无登录态,浏览器验收(刷新仍在 A、粘贴 `/?c=`、A→B→C 后退、删除死链、流式中切走再 back、401 回跳)未做,由合同测试覆盖。浅色/深色:新文案「该对话不存在或已被删除」走既有 sonner toast`已被删除` 命中 `failedNotice` 用 error 语气,颜色仍是 `--color-canvas` / `--color-ink`
## 2026-09-01 - TASK-cloud-truth-convergence:星盘库 / 合盘历史 / 置顶归档收归云端
- 星盘库启动只读 `fetchCloudChartLibrary`self 仍由 profile 重建),合盘历史用云端列表整体替换。`jyotisha_chart_library:*``jyotisha_synastry_history:*` 停读写,启动 `removeItem`。云端读失败给出重试,不再静默用本地副本。
- 保存/删除星盘:云端成功才改 state。失败保留表单或列表行,提示「保存失败,请重试」/「删除失败,请重试」,不再有 `cloudSaved` 或「已保存到本地」。合盘保存失败报告留在当页,提示「未能存入历史」,不写本地历史。
- `chat_sessions` 增加 `pinned boolean not null default false``archived_at timestamptz null`(只加列)。列表/详情 SELECT 带上这两列;置顶/归档走既有 PATCH,乐观更新,失败回滚。本地 `jyotisha-session-controls` 一次性导入后删键。每日星语缓存与 `activeChartId` 未动。
- 迁移额外 `grant update (pinned, archived_at)`:原表 update 是列级授权,不加新列 grant 则 PATCH 会失败。未改写既有 grant,也未复制进 `frontend/db/migrations`
- 断言例外(锁住的正是本轮要修的缺陷):
- `chart-library-other-profile.test.ts`:原值 `let cloudSaved = false`、catch 文案「已保存到本地星盘库;云端同步失败」、`localStorage.setItem(chartLibraryStorageKey…)`、删除「已从本地星盘库删除」。现为失败即失败。
- `chart-library-session.test.ts`:原值 `keepLocalChartLibraryOnCloudFailure(local) === local`。现为只保留 profile 重建的 self。
- `tests/test_supabase_user_data_contract.py`:原值页面必须含 `localStorage.setItem(chartLibraryStorageKey…)``chartLibraryStorageKey``synastryHistoryStorageKey``Cloud chart library is best-effort``writeSynastryHistory(accountId, next)`
- `chat-session-authority.test.ts`:列表/详情列字符串原在 `updated_at` 结束;现含 `pinned,archived_at`。列表仍不得带 `messages`
- `next build`:因本 worktree 的 `node_modules` 是指向其他 worktree 的符号链接,默认 Turbopack 拒绝;改用 `next build --webpack`。路由表仍是 `┌ ○ /`Static)。`/login` 仍是 `ƒ`
- 本地验证:
- `./node_modules/.bin/tsc --noEmit` 通过。
- 非数据库前端测试:**2393 通过 / fail=0 / skipped=0**。
- `npm run test:db`**34 通过 / fail=0 / skipped=0**。第二次整组为干净通过;第一次整组里 `database-admin-account-reset` 在 Docker 刚起来时 migration status=1,单测重跑即过。业务库测试 stdout 含 `applied 20260901020000_chat_session_pin_archive.sql`,幂等重放有 `column "pinned"/"archived_at" already exists, skipping`
- 合计 **2427 ≥ 2424**
- 实测:无登录态,未做浏览器里断网保存、云端删除后刷新、双 profile 置顶一致性、localStorage 键审计。由合同测试覆盖。浅色/深色:新文案「保存失败,请重试」「未能存入历史」「星盘库暂时无法读取,请重试。」走既有 sonner,`失败`/`未能`/`无法` 命中 `failedNotice` 用 error 语气,颜色仍是 `--color-canvas` / `--color-ink`
- 未提交、未推送。