① 状态板校正: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
150 lines
9.3 KiB
Markdown
150 lines
9.3 KiB
Markdown
# TASK · page.tsx 状态下沉第二批:session / profile / synastry 三簇 + 稳住外壳 setter
|
||
|
||
- 日期:2026-09-16
|
||
- 基线 commit:`origin/staging` @ `4f643aa0`(开工时以最新 `origin/staging` 为准,数字全部重测)
|
||
- 执行分支:`codex/home-state-lowering-batch2-20260916`
|
||
- 落点:`frontend/src/app/page.tsx`、`frontend/src/hooks/use-session-management.ts`、`frontend/src/hooks/use-profile-onboarding.ts`、`frontend/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()` 的 `useState` 从 **52** 降到 **≤ 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. 开工前置命令
|
||
|
||
```bash
|
||
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`(第一批的分类表与收尾实测,是本单的格式范本)。
|
||
|
||
验收命令:
|
||
|
||
```bash
|
||
./node_modules/.bin/tsc --noEmit
|
||
npm run lint # 0 error,warning 必须 ≤ 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-733**;734/735 已被 `TASK-consultation-residual-hotspots-20260916` 预占。
|
||
|
||
## 9. 不在本单范围
|
||
|
||
- 其余 32 个分散状态(没有成簇,逐个搬性价比低)
|
||
- Context Provider 或外部 store
|
||
- 任何交互缺陷(本单零行为变化)
|
||
- API server 一侧(另一条线)
|