Files
Jyotisha/PROGRESS-home-split-20260901.md
T
Jesse_Chen 54269fcfcc
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
refactor(chat): extract home helpers, chart library, and starter surfaces
page.tsx still owns the chat main chain, but the first product surfaces now
live in their own modules so later splits can land without editing the 4k-line
Home. Source-lock tests follow the moved tokens; the orphan user-data contract
is aligned and added to the quick gate.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 22:58:02 +08:00

104 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROGRESS · 拆分首页巨石组件·第一批(2026-09-01)
工作树:`.worktrees/home-split-20260901`
分支:`codex/home-split-20260901`(跟踪 `origin/staging`
基线:`origin/staging` @ `85589005`(任务书提交;产品代码与 P2a `ce6a8a7e` 相同)
不要写成 `PROGRESS.md`。本轮未提交、未推送。
## 度量
| 项 | 拆前 `85589005` | 拆后 | 说明 |
| --- | ---: | ---: | --- |
| `frontend/src/app/page.tsx` 行数 | 4766 | 3505 | 目标 ≤3000,未达标 |
| `useState(` | 26 | 26 | 见下方 overlay 说明 |
| `useEffect(` | 20 | 20 | 拉取/重试 effect 仍在 Home |
| `/` 路由 | `○ Static` | `○ Static` | webpack `next build` |
| 首屏 JS gzip -9 | 500262 B = 488.5 KB | 501315 B = 489.6 KB | +1053 B / **+0.21%**(±2% 内) |
| 前端测试 | 2427 | 2427 | fail=0 skipped=0(见验证) |
未达标原因:聊天主链路(composer / transcript / `send` / 停止与恢复 / 引导对话)按任务书本批不动。抽走的是 helpers + 星盘库/合盘面板 + starter/每日星语。剩余约 505 行要等第二批。
`useState` 未下降:`otherProfileDraft` / `editingChartId` / `otherChartRelationship` / `editingSelfChart` 仍留在 `Home``AccountDialogOverlay` 在关闭时 `return null`,把独占 state 下移进面板会在关弹窗时丢掉未保存草稿,属于行为变化,本轮禁止。handlers(`saveOtherChart` 等)已随 JSX 进面板,state 经显式 props 传入。
## 任务 0 · 孤儿契约测试
`tests/test_supabase_user_data_contract.py` 对齐现状源码(性质保留:浏览器不直写 `profiles` / `chat_sessions`,账户 PATCH 仍拒数组,合盘仍走 `postPython("/api/chart")`)。任务书写的三处之外,同一文件里还有过期 token,一并换成现码并在上方注释原值:
- 首页不再 `.from("profiles")` / `.from("chat_sessions")`,锁 `fetch("/api/account"` / `fetch("/api/sessions"`
- 账户 PATCH`accountProfilePatchSchema.safeParse` + `z.object({``account-profile-patch.ts`
- 文案「添加其他人的星盘」
- 合盘:`postPython("/api/chart", selfPayload)` / `partnerPayload`
- 用户消息:`messages: questionAlreadyPresent ? preservedMessages : [...preservedMessages, { role: "user", text: question }]`
- 中断路径:源码已无 `await persistSession(interruptedSession)`;停止文案「正在停止回答并申请退回本次点数…」
搬家后该文件改读 `_home_surface()``page.tsx` + 抽出文件拼接),正则/token 未改。
`scripts/run_quality_gate.py``CORE_PYTEST_TARGETS` 已列入此文件,注释写明前端搬家轮必须带着它跑。
`pytest tests/test_supabase_user_data_contract.py tests/test_daily_and_rectification_entrypoints.py -q` → 12 passed。
## 任务 13 · 搬家
新文件(实现从 `page.tsx` 原样搬出,加 `export`):
| 文件 | 行 | 内容 |
| --- | ---: | --- |
| `frontend/src/lib/home-types.ts` | 254 | 类型、空资料、themes、storage 键常量 |
| `frontend/src/lib/home-profile.ts` | 323 | 地点/资料/标签/`readProfile`/`upsertSelfChart` |
| `frontend/src/lib/home-cloud-sync.ts` | 499 | 云端 fetch、登录跳转、每日星语读写 |
| `frontend/src/components/birth-location-fields.tsx` | 40 | `BirthLocationFields` |
| `frontend/src/components/profile-fields.tsx` | 38 | `ProfileFields` |
| `frontend/src/components/onboarding-chat-message.tsx` | 28 | `OnboardingChatMessage` |
| `frontend/src/components/chart-library-panel.tsx` | 269 | 星盘库 + 合盘卡/历史/他人表单 |
| `frontend/src/components/starter-home.tsx` | 159 | starter hero / 每日星语 / 生时入口 / 主题卡 |
`page.tsx``"use client"``import "@/app/site-styles"``const BirthTimeRectification = dynamic(...)`。新组件未 import 全局样式。无 context/store、无手写 `useCallback`/`useMemo`、未重开 React Compiler。
本人星盘表单仍 `onSubmit={saveProfile}`(面板 prop 名就是 `saveProfile`)。starter 回调 prop 保持原标识符:`startDailyStarlanguageConsultation``openRectificationFromHomepage``startSuggestedConsultation`
## 合同测试路径(同一 token,只换读取面)
共用拼接件 `frontend/tests/home-surface.ts``page.tsx` + 上表抽出文件。Python 侧 `_home_surface()` / 显式 concat 同理。
| 测试 | 原路径 | 新路径 |
| --- | --- | --- |
| `birth-place-picker.test.ts` | `src/app/page.tsx` | `homeSurface``BirthPlacePicker``birth-location-fields.tsx` |
| `birth-time-consultation-consent.test.ts` | `page.tsx` | `homeSurface``readProfile``home-profile.ts` |
| `character-remaining-contract.test.ts` | `page.tsx` | `homeSurface`(姓名字数 `aria-describedby``profile-fields.tsx` |
| `chart-library-other-profile.test.ts` | `page.tsx` | `homeSurface` |
| `chat-navigation-a11y-contract.test.ts` | `page.tsx` | `homeSurface` |
| `chat-session-authority.test.ts` | `page.tsx` | `homeSurface` |
| `chat-session-url.test.ts` | `page.tsx` | `homeSurface` |
| `chat-session-write.test.ts` | `page.tsx` | `homeSurface``fetch("/api/sessions"``home-cloud-sync.ts` |
| `composer-isolation-contract.test.ts` | `page.tsx` | `homeSurface``pendingConsultationStorageKey``home-types.ts` |
| `consultation-entrypoint.test.ts` | `page.tsx` | `homeSurface`starter 卡在 `starter-home.tsx` |
| `consultation-recovery.test.ts` | `page.tsx` | `homeSurface` |
| `daily-starlanguage.test.ts` | `page.tsx` | `homeSurface` |
| `membership-page.test.ts`home 段) | `page.tsx` | `homeSurface``LoginRedirectError``home-cloud-sync.ts` |
| `onboarding-presentation.test.ts` | `page.tsx` | `homeSurface` |
| `rectification-agentic-entry.test.ts` | `page.tsx` | `homeSurface` |
| `settings-mvp-contract.test.ts` `renderProfile` | `page.tsx` 切片 | `homeSurface`(切片标记仍在 `page.tsx` |
| `settings-mvp-contract.test.ts` 星盘库表单 | `page.tsx``renderChartLibrary``renderGeneral` 切片 | `chart-library-panel.tsx`(切片里只剩 `<ChartLibraryPanel />`token 已搬走) |
| `starter-questions.test.ts` | `page.tsx` | `homeSurface` |
| `tests/test_supabase_user_data_contract.py` | `PAGE.read_text()` | `_home_surface()` |
| `tests/test_daily_and_rectification_entrypoints.py` | `PAGE` | `PAGE` + `starter-home.tsx` + `home-cloud-sync.ts` |
| `tests/test_birth_time_journey_contract.py` 网页引导条 | `page.tsx` | `page.tsx` + `home-profile.ts``reported_birth_time` / `active_birth_time` |
未改断言语义。锁聊天主链路、且 token 仍在 `page.tsx` 的测试继续只读 `page.tsx`(如 `site-style-isolation-contract`、composer/sidebar 壳、`rectification-lazy-loading`)。
## 验证
- `./node_modules/.bin/tsc --noEmit`:通过。
- `npm test`2427 条。并发下 2 条 Docker 库测 flake`admin-database` / `model-configuration-security``database migration failed` / `Connection terminated unexpectedly`)。`--test-concurrency=1` 重跑这 8 条:pass 8 fail 0。与产品搬家无关。skipped=0。
- `./node_modules/.bin/next build --webpack``┌ ○ /`。本树 `node_modules` 仍是指向 `session-url-20260901` 的符号链接,默认 Turbopack 会拒。gzip 口径:预渲染 `index.html` 引用的 `/_next/static/**.js` 去重后 `gzipSync` level 9。基线用同 SHA 干净 worktree 同口径对照。
- 行为抽查:无登录态,未在浏览器点星盘库增删改、合盘、starter 入口、每日星语。由合同测试覆盖。
## 明确未做 / 未修
- 聊天主链路第二批再拆。
- popstate 回默认会话未走 `selectSession`(任务书决策 4)。
- `tests/test_session_management_entrypoints.py::test_archiving_never_calls_the_delete_endpoint` 仍锁已删除的 `setArchivedSessionIds`P2a 遗留,不在 `CORE_PYTEST_TARGETS`,本轮不顺手修)。
- `tests/test_birth_time_journey_contract.py::test_web_onboarding_uses_the_deterministic_free_journey` 在 mastra 断言 `'entry_mode: entryMode'` 上仍红(与搬家无关、不在 quick gate);本轮只补了 `page.tsx` 侧 token 路径。
- 未改 `.gitea/workflows/**`。未提升 `main`