Files
Jyotisha/PROGRESS-home-split-batch2-20260901.md
T
Jesse_Chen 551d6317ae
Independent Staging Quality Gate / validate (push) Has been cancelled
Independent Staging Quality Gate / publish (push) Has been cancelled
refactor(chat): extract consultation and session hooks after contract repairs
Keep archive as a PATCH of archived_at rather than DELETE, pass entry_mode through onboarding, and let popstate to the default chat reuse selectSession. Then move send/stop/recovery and session management out of page.tsx so the home surface stays within the batch-two line budget.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 04:34:14 +08:00

8.0 KiB
Raw Blame History

PROGRESS · 拆分首页巨石组件·第二批:聊天主链路(2026-09-01)

工作树:.worktrees/contract-repairs-20260901
分支:codex/contract-repairs-20260901
基线:小刀轮未推送,故未另开 codex/home-split-batch2-20260901;产品代码从 a6148af8 + 小刀轮改动继续。

不要写成 PROGRESS.md。交付为快进推 origin/staging

React Compiler 仍关(BLOCKED.md 2026-08-17)。未引入 context/store。无手写 useCallback/useMemo。自定义 hook 按任务书决策记录 1 允许。site-styles import 仍在 page.tsx 顶。const BirthTimeRectification = dynamic(...) 未动。

度量

拆前(第一批后 3505 / 小刀后约 3510 拆后 说明
frontend/src/app/page.tsx 行数 3505 2445 目标 ≤2600,达标
useState( Home / session hook / consult hook 26 / — / — 26 / 0 / 0 独占 state 未下移,见 hook 顺序
useRef( Home / session / consult 19 / — / — 19 / 0 / 0 同上
useEffect( Home / session / consult 20 / — / — 20 / 0 / 0 拉取/恢复 effect 仍在 Home
/ 路由 ○ Static ○ Static webpack next build --webpack
首屏 JS gzip -9 第一批后 501315 B 501104 B = 489.4 KB 211 B / 0.04%(±2% 内)
前端测试 小刀后 2428 2428 见验证

剩余未达标块(第三批):onboarding/profilerefreshAccountsignOut)、rectification 胶水(refreshRectificationEntrySummaryhandleRectificationMessagesChange)、合盘草稿、composer submit

Hook 调用顺序(红线 1

搬前 Home 内真正的 React hook 序列(a6148af8):

useRouteruseState×26 → useRef×19 → useBirthTimeGuidedJourneyuseEffect×8 → useConversationScrollAnchoruseEffect×12

咨询/会话的 useState/useRef 不是连续块:中间夹着校正会话、引导草稿、星盘库、合盘等。若只把「引擎独占」的那几项抠进 hook,会改变 Home 里 hook 的相对次序。

因此本轮两个新 hook 内部零 useState/useRef/useEffect,只搬函数体与 .current = 赋值。串接后 useState/useRef/useEffect 次序与搬前逐一相同;新增的只是两个无内部 hook 的调用点:

调用点 位置 原因
useSessionManagement(...) useBirthTimeGuidedJourney 之后、第一条 useEffect 之前 紧随其后的 effect 调用 ensureSessionMessages
useConsultationRun(...) useConversationScrollAnchor 之后、其余 useEffect 之前 send 需要 conversationAnchor.anchorToLatest()

依赖方向:session hook 先返回 persistSession / updateSession / startNewChat / continueInNewChat,由 Home 传入 consult hook。两文件 不得、也没有 互相 import。

setDraft / setDraftTheme / setDraftEntrypoint / refreshAccount / openAccountDialog / openRectificationFromHomepage / openRectificationSession 仍是 Homefunction declaration(JS 提升),所以可以出现在 hook 调用点之上的参数列表里。这不是 React hook 顺序问题。

核对方式:对 export default function Home 之后的 useRouter|useState|useRef|useEffect|useBirthTimeGuidedJourney|useConversationScrollAnchor|useSessionManagement|useConsultationRun 计数;两 hook 文件内上述符号计数为 0。

任务 12 · 搬家

新文件(函数体与 a6148af8page.tsx 逐行一致;允许差异仅缩进、export、经参数/返回值改道的标识符。popstate 以小刀轮为准,不回退到 a6148af8):

文件 内容
frontend/src/hooks/use-session-management.ts 443 updateSessionselectSessionModel + 小刀修过的 applySessionPopStateRef.current
frontend/src/hooks/use-consultation-run.ts 1073 restoreConsultationRecovery + recovery/replay 赋值、requestCancellation / confirmCancellation / stopResponse / completeConsultationInterface / send / regenerateLatestAnswer

函数体公证(对 a6148af8 去缩进后逐行):

updateSession 3、persistSession 25、ensureSessionMessages 24、continueInNewChat 7、renameSession 11、deleteSession 20、togglePinnedSession 10、toggleArchivedSession 22、shareSession 28、startNewChat 33、startConsultationAfterRectification 5、selectSession 28、selectSessionModel 52、restoreConsultationRecovery 53、requestCancellation 27、confirmCancellation 19、stopResponse 129、completeConsultationInterface 9、send 567、regenerateLatestAnswer 23consultationRecoveryCheck.current / consultationReplay.current 赋值块亦相同。

改名清单:(无业务标识符重命名)。

applySessionPopStateRef 相对 a6148af8 的差异即小刀轮任务 3,原样搬进 session hook。

合同测试路径(同一 token,只换读取面)

拼接件 frontend/tests/home-surface.ts / Python _home_surface():第一批文件 + 可选 use-session-management.ts / use-consultation-run.tsexistsSync / Path.exists())。hook 落地后自动拼进。

测试 原路径 新路径
sidebar-contract.test.ts「keeps the page session selection callback…」 page.tsx 正则 selectSession homeSurface(函数已搬走;断言内容未改)
consultation-birth-time-mode.test.ts homepage consultationMode: page.tsx homeSurfacetoken 在 send
tests/test_supabase_user_data_contract.py 已是 _home_surface() 可选 hook 列入清单(persistSession(completedSession) 等在 consult hook
rectification-agentic-entry.test.ts refreshAccount 切片 function updateSession 作终点 function openAccountDialogupdateSession 已搬走;若终点落在拼接后的 hook 文件,切片会吞进仍留在 page 的 persistProfile/setProfileDraft。断言内容未改)
profile-state.test.ts 同一切片 同上 同上(该文件仍只读 page.tsx,终点改为仍相邻的 openAccountDialog
chat-stream-layout.test.ts 活动/ndjson/regenerateLatestAnswer page.tsx homeSurfacetoken 在 send / consult hook
evidence-audit-panel.test.ts workflow receipt headers page.tsx homeSurface
chat-notice-and-scroll-contract.test.ts send 切片 page.tsxupdateSession(sessionId, () => userSession) homeSurface(仅该条;JSX/poll 仍读 page.tsx

其余已走 homeSurface 的聊天主链路测试(chat-session-url / consultation-recovery / consultation-entrypoint / composer-isolation / chat-session-authority 等)无需再改:切片标记仍在 hook 文件内且相邻。

锁 JSX/仍留在 page.tsx 的测试继续只读 page.tsxsite-style-isolationrectification-lazy-loadingchat-notice-and-scroll 的 poll timer、profile/onboarding 等)。

小刀轮两个 Python 文件保持全绿(见小刀 PROGRESS)。

验证

  • ./node_modules/.bin/tsc --noEmit:通过。
  • 聚焦合同:consultation-recovery / chat-session-* / composer-isolation / consultation-entrypoint / starter-questions / chat-navigation-a11y / settings-mvp / sidebar-contract / consultation-birth-time-mode / rectification-agentic-entry / profile-state 全绿。
  • 全量 npm test2428 pass / 0 fail / 0 skipped。
  • ./node_modules/.bin/next build --webpack┌ ○ / Static。首屏 JS gzip-9 501104 B vs 第一批后 501315 B(−211 B / 0.04%)。
  • 行为抽查:无登录态浏览器点选会话 / 发送咨询。由合同测试覆盖抽取正确性;popstate 行为变化已在小刀轮用源码合同锁住。

未改 .gitea/workflows/**。未动数据库。未提升 main。未重开 React Compiler。

明确未做

  • onboarding/profile 簇与 rectification 胶水(第三批)。
  • 未把 streaming/pending 等 state 下移进 hook(为保住 hook 顺序)。
  • 未修任何行为(popstate 已在小刀轮完成)。