Files
Jyotisha/docs/tasks/TASK-home-state-lowering-batch2-20260916.md
T
Jesse_ChenandClaude Opus 5 37e6c519f7 docs(tasks): 校正状态板 + 状态下沉第二批 + 后门单 + 对账清单
① 状态板校正:09-15~16 这 10 份任务书的实现早已合入 staging 并经逐单
   验收,状态板却仍写「待领取 / 待验收」。改成「已验收」并补上落点 SHA
   与验收要点;顺带补齐 8 个 PROGRESS 列。防复发写进「命名与归档」:
   实现合入的同一次推送必须同时改状态板那一行。

② 新增 TASK-home-state-lowering-batch2-20260916(不占 BUG 号):
   第一批 f8e607c2 已验收(useState 66→52、useRef 41→39、散装
   rectification* 归零)。本单搬剩下三簇 session*10 / profile*6 /
   synastry*4,目标 52→≤36;并修第一批尾巴——
   createRectificationShellSetters 每帧新身份多出的那条 exhaustive-deps
   warning(119→120),正解是稳住 setter 身份而不是塞进 deps。

③ 新增 TASK-api-server-backdoor-close-20260916(不占 BUG 号):
   实测四处 __new__ 的传递闭包只有 8 方法 / 314 行且 0 个碰 HTTP 上下文,
   占全类 4%。所以关后门不必捆绑 2,000+ 行体量搬运。产品拍板阶段 2/3
   不立单,由 3b17c1b2 换好的门禁长期推进。原 decomposition 单标为已取代。

④ 新增 RECONCILE-20260916:另外 7 份 09-10~14 的单没有 PROGRESS、但
   引用的 BUG 号都是 resolved,无法从 README 判断,列成一页纸让执行方
   回填;另附三条确定没做的证据、两条未闭环状态、BLK-001 仍红。

纯文档推送,不触发门禁、不发布镜像、不部署。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-16 01:13:26 +00:00

9.3 KiB
Raw Blame History

TASK · page.tsx 状态下沉第二批:session / profile / synastry 三簇 + 稳住外壳 setter

  • 日期:2026-09-16
  • 基线 commitorigin/staging @ 4f643aa0(开工时以最新 origin/staging 为准,数字全部重测)
  • 执行分支:codex/home-state-lowering-batch2-20260916
  • 落点:frontend/src/app/page.tsxfrontend/src/hooks/use-session-management.tsfrontend/src/hooks/use-profile-onboarding.tsfrontend/src/hooks/use-rectification-surface.ts、以及为合盘新建的 hook
  • 串行在 f8e607c2(第一批)之后,已满足
  • TASK-consultation-residual-hotspots-20260916(纯 Python)、TASK-api-server-backdoor-close-20260916(纯 Python无文件重叠,三单可并行
  • 规模:照第一批的成方再搬三簇。零行为变化、零文案变化。

1. 第一批已经证明这条路走得通

f8e607c2 把 15 个 rectification* 状态搬走,我验收实测:

指标 第一批前 第一批后
Home()useState 66 52
Home()useRef 41 39
page.tsx 行数 1,951 1,931
残留散装 rectification* state 15 0

做法是:先把 15 个逐条分类成「只服务子树」与「外壳也要读」,前者搬进 useRectificationSurface,后者合并成一个对象 state。全量前端套件两侧完全相同(3329 tests / fail 31,失败清单逐条一致),首屏 gzip 0.00 % 变化,/○ Static。增长冻结基线往紧里收66/41/1951 → 52/39/1931)。

本单把同一套做法用在剩下的三簇上。

2. 事故实证:剩下的 52 个里还有 20 个是成簇的

Home() 现在 52 个 useState,按前缀分群:

个数 已经有的抽取点
session* 10 use-session-management.ts(参数式,解构约 40 个参数)
profile* 6 use-profile-onboarding.ts
synastry* 4 无,散在 Home()
其余分散 32

useSessionManagement(params) 的第一件事仍然是解构约 40 个参数——第一批没有碰它。这就是「代码搬走了、状态没搬」的残留部分。

另有第一批留下的一个小尾巴(执行方已在进度记录里主动披露,判断正确):

createRectificationShellSetters(setRectification) 在 render 体里无记忆化调用,每帧返回新的函数身份,于是入口摘要那个 useEffect 多了一条 react-hooks/exhaustive-deps warning(全仓 119 → 120)。进度记录写明「不能把它们放进 deps,否则每帧重拉摘要」——这个判断是对的,我核过:那几个 setter 都只是 setRectification(prev => ...) 的包装,任何身份行为都一样,当前是安全的。但它是个陷阱:后面任何人为了消除 warning 把它们塞进 deps,就会造成每帧重新拉取入口摘要。

3. 决策记录

产品 2026-09-16 授权本单,口径与第一批一致:

  1. 继续走「状态下沉」,不引外部 store、不铺全局 Context Provider(第一批已否决这两条,本单不重开)。
  2. 抽出去的 hook 与子组件持有自己的状态——AGENTS.md §6 已于 3b17c1b2 改写,「参数式 hook 内部保持 0 个 React hook」那条红线已经推翻。执行方不得以旧 AGENTS 为由拒改。
  3. 零行为变化。 本单不修任何已知交互缺陷,发现了写进进度记录。
  4. 那条 warning 要在本单里消掉,做法是稳住 setter 身份,不是把它们加进 deps。

4. 硬红线

  1. 先分类再动手。 三簇共 20 个状态,每一个都要归到「只服务子树 → 搬下去」或「外壳也要读 → 合并成一个对象」,分类表连同「谁在读」写进进度记录,一个不漏。第一批的分类表是格式范本。
  2. 零行为变化是唯一成败判据。逐条对照:会话列表加载/翻页/切换/归档/置顶/重命名/删除、模型切换与同步失败、资料引导各步、头像上传、合盘发起与历史、写满后开新对话。
  3. next build/ 仍须 ○ Static;首屏 gzip 变化在 ±2 % 内(第一批实测 130,872 B,同一种量法)。
  4. 测试总数不得低于开工时 origin/staging 的实测;改任何既有断言必须写「原值 / 新值 / 原因」三栏(AGENTS §7.3)。第一批那批源码正则合同(foo={bar}foo: bar)是可接受的改法范本:主语不许变
  5. npm run lint 的 warning 数不得上升,并且本单要把 120 降回 119(消掉 §2 那条)。
  6. 不得新写第二个聊天输入框、第二套滚动跟随、第二套加载动画(§6 第三条原样有效)。
  7. 不得顺手升级依赖、不得顺手修不在本单里的 warning。

5. 任务分解

5.1 稳住外壳 setter,消掉那条 warning(先做,最小)

createRectificationShellSetters(setRectification) 的结果记忆化(useMemo,依赖只有 setRectification,而它是 React 的稳定 setter),使四个 setter 身份跨帧稳定;然后把它们按 eslint 的要求补进那个 useEffect 的 deps。

  • 验收:npm run lint 从 120 warning 回到 119,且没有新增任何其它 warning(按规则+信息归一化比对,不要只比数字)。
  • 验收:入口摘要的 effect 仍然只在 accountId / bootstrapPhase 变化时触发——新增一条断言或在进度记录里给出证明,不得靠肉眼

5.2 synastry* 四个下沉(第二小,边界最清楚)

synastryRelationshipType / synastryPendingId / synastryReportCard / synastryHistory 目前散在 Home() 里,没有对应 hook。新建一个 hook 或直接让合盘子树持有。

  • 验收:Home()const [synastry 的出现次数为 0
  • 验收:合盘发起、失败、历史列表三条路径行为不变。

5.3 profile* 六个下沉

use-profile-onboarding.ts 已存在(445 行,参数式)。改成持有自己的状态。注意资料引导与 bootstrapPhase、揭幕门耦合较深,分类时要特别小心哪些是外壳要读的。

  • 验收:分类表里每个 profile* 都写明谁在读。
  • 验收:Home() 里散装 profile* state ≤ 1(合并对象),多留必须逐个说明理由。

5.4 session* 十个下沉(最大、最后做)

use-session-management.ts 是三簇里耦合最深的(约 40 个参数,522 行),而且它和校正面有交叉(第一批的进度记录写明:useSessionManagement 必须在 surface hook 之前调用,用 rectificationSessionOpenerRef 把 opener 递过去)。这条交叉关系不得破坏

  • 验收:useSessionManagement 的参数个数显著下降,新值写进进度记录(改前约 40)。
  • 验收:Home() 里散装 session* state ≤ 2
  • 验收:rectificationSessionOpenerRef 那条调用顺序约束仍然成立,并有一条断言钉住。

5.5 收口指标

  • 验收:Home()useState52 降到 ≤ 36(三簇共 20 个,允许留 ≤ 4 个在外壳);useRef 不得上升(改前 39)。
  • 验收:frontend/tests/home-shell-growth-contract.test.ts 更新为新基线(只许往紧里收),并贴一次反向验证(人为加一个 useState 必须变红)。
  • 验收:全量前端套件失败清单与开工基线逐条一致。

5.6 真人清单

docs/testing/home-state-lowering-20260915.md 的格式,为本单三簇补一份可照做的走查条目(本仓无浏览器与登录态)。

6. 让步顺序

  1. 5.1 必须做,它是第一批留下的尾巴,最小。
  2. 5.2 → 5.3 → 5.4 按由易到难推进。做不完可以只交前两簇,砍掉的簇在进度记录里写明,并把 5.5 的目标值按实际达成调整(只许往紧里收,不许放松)。
  3. 5.5、5.6 不得砍。

7. 开工前置命令

git fetch origin --prune
git worktree add -b codex/home-state-lowering-batch2-20260916 \
  .worktrees/home-state-lowering-batch2-20260916 origin/staging
cd .worktrees/home-state-lowering-batch2-20260916/frontend
git status -sb | head -1
npm ci
# 重测基线,不要抄本任务书里的数
grep -cE '\buseState[<(]' src/app/page.tsx
grep -cE '\buseRef[<(]' src/app/page.tsx
for p in session profile synastry; do printf "%s: %s\n" "$p" "$(grep -cE "const \[$p" src/app/page.tsx)"; done
npm run lint 2>&1 | tail -2

开工前必读:docs/tasks/PROGRESS-home-state-lowering-20260915.md(第一批的分类表与收尾实测,是本单的格式范本)。

验收命令:

./node_modules/.bin/tsc --noEmit
npm run lint                       # 0 errorwarning 必须 ≤ 119
npx tsx --test tests/home-shell-growth-contract.test.ts tests/rectification-*.test.ts \
  tests/chat-session-*.test.ts tests/session-*.test.ts
npx tsx --test tests/*.test.ts     # 与基线逐条比对失败清单
npm run build                      # `/` 仍须 ○ Static

8. BUG 编号起点

本单不占 BUG 号(结构改造,不是缺陷)。基线 4f643aa0 上最大号 BUG-733734/735 已被 TASK-consultation-residual-hotspots-20260916 预占。

9. 不在本单范围

  • 其余 32 个分散状态(没有成簇,逐个搬性价比低)
  • Context Provider 或外部 store
  • 任何交互缺陷(本单零行为变化)
  • API server 一侧(另一条线)