Files
Jyotisha/docs/tasks/PROGRESS-people-archive-p1-fix-20260925.md
T
jesse-uxandClaude Code 4d801e53c3
Independent Staging Quality Gate / validate (push) Successful in 16m28s
Independent Staging Quality Gate / publish (push) Successful in 3m33s
fix: integrate people archive, report reader and western chart corrections
Validate on Linux Node 22 and PostgreSQL 17: 3894 frontend tests and 64 database tests pass, with no removed test names or new failures. Preserve static Home, bounded gzip, assertion-change records and manual acceptance gaps.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-25 20:41:16 +08:00

116 lines
14 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 · 人物档案 P0/P1 修复(2026-09-25)
## 最终整合复验补记
Linux Node22.23.2 / PostgreSQL17 的 `final-r4b`:全量 **3894/3894**、DB **64/64**,fail/skip/cancel/todo 均0;tsc/lint/build各exit0,lint0error/127既有warning,首页Static。相对开工基线3863/61,顶层及嵌套名称多重集合均无删除、新增失败0。三种首页gzip变化为完整资源+0.1612%、入口增量−0.4536%、专属JS−0.7984%。日志、快照hash、四项修复三栏及验证环境失败保留在 `PROGRESS-three-fixes-integration-20260925.md` final-r4b节。
以下执行期记录保留作历史;旧面板在整合树保留,不能将本单执行树的删除写成已交付。Python/隐私及最终边界核查另行补记;受控真人、迁移上线和health仍待验,未据自动化绿提前resolved。
## 基线与门禁
- 开发树:`codex/people-archive-p1-fix-20260925`,实际开工基线 `48fe4daf519dab2a5c6bf4b01dd513067de1647b`(任务书之后的新 staging)。不改其它分支、workflow、DNS;未提交、未推送。
- **必须用 Node 22 跑全量测试,并和开工时的基线逐条对比,新增失败为 0 才能推;改任何断言都要写三栏。**
- 协调方 Linux Node22 基线:前端 3863/3863、fail0、skip0;数据库 61/61;tsc exit0。旧 Node20 的失败不作为本轮豁免。
- 当前仅本地定向证据:Node v22.23.2,首轮组合 70/70,provider/report/cache 39/39;tsc exit0;前端修改区域 lint 0 error(既有 warning 未顺手修改);根 Python 三个相关合同 21/21。新增星历用例、Linux全量与DB快照审查仍进行中,完成后由协调方补确数。
## 实现清单
| 任务 | 实现 | 验收状态 |
|---|---|---|
| T1 worker | 持久化 chartProfileId 经 loadSubjectBirth;他人从 typed columns 读取;候选范围仅本人;人物缺失/外属终止且走既有退款 | fake-engine ready 与删除/外属失败退点定向通过;真实模型/线上待验 |
| T2 OR is | 复用 unary IS 编译器,支持 null/true/false,不当作字符串或 =null | 单测通过;真实 sessions GET + PG 在新增 DB 用例中 |
| T3 时序 | 同步 last-account 预读仅作暂存选择;账户/目录校验 ready 闸门挡 chart/report/ephemeris/newChat;provider先账户再目录再session | 跨账户/目录事件单测通过,受控浏览器待验 |
| T4 消息 | metadata merge 保留 hydrated 消息、深链及分页外行;人物不变不广播subject;视图按当前人物过滤,跨账户清除旧数据 | 纯函数与provider合同通过,生命周期独立审查中 |
| T5 纠偏 | 新迁移降级旧JSON accepted/confirmed、清active tuple;不改旧迁移、不改profiles;目录失效刷新;未知用量拒绝删除;daily按所选资料;合盘新对话显式self且不改全局;星历暖缓存/首败重试 | 定向通过;迁移与真机待独立验 |
| T6 清理 | 有界 ids 预检替代count/head;同账户事务锁确保4人上限;无效UUID 404;report双字段冲突400并规范化持久化;删除死面板、合同改锁/people;编辑标题纠正 | DB并发用例新增,所有既有测试名保留 |
| T7 记录 | BUG1031/1032,关联1030/990/1024;本记录、设计、changelog、真人清单 | BUG状态保持 investigating,未部署 |
## 数据边界与设计说明
- 检查迁移:`personal_reports.chart_profile_id` 为 nullable uuid,无指向 chart_profiles 的 FK;不存在 ON DELETE SET NULL 把他人改成本人的窗口。**独立真实DB进一步确认:删除RPC级联删报告/job后,worker不会再看到缺失人物,单靠worker失败退款不足。** 新 `20260925040000_deleted_report_release.sql` 在删除事务内以受限definer触发器复用`release_usage`,未交付预留退款;ready不退,已completed不退,已released幂等。删除RPC显式校验auth.uid/所有权并按job→report锁序避免running worker完成时死锁。未改旧迁移、未开放通用退款权限。
- 新纠偏迁移在独占表锁事务中临时停用 birth guard,清理完立即恢复。旧JSON保留作兼容,不再赋予校正权威。profiles不写入。
- 人数上限使用 owner 派生的事务 advisory lock 后再独立 count,两个连接争抢第四/第五个名额;预检只改善错误反馈,DB为最终权威。
- Provider内部保留同账户会话,以免深链/消息丢失;可见侧栏按当前人物过滤,不展示对方列表。不同账户不能合并。
- Home未新增useState/useRef。Part B为纯编码豁免。Skill版本不bump。
## fabe0114 追溯三栏(完整覆盖11个文件、12个修改位置)
| 文件/断言 | 原值 | 新值 | 原因 |
|---|---|---|---|
| chart-page-view / provider URL | sessions仅limit | limit+subject | 历史按当前人物;本轮进一步用bind后捕获subjectId |
| chart-view-route / birth reader | ACCOUNT_BIRTH_SELECT直读 | loadSubjectBirth且拒clientBirth/body.profile | 唯一服务端人物解析入口 |
| consultation-entrypoint / disabled | 产品/加载/变更3条件 | 加 !rectificationForSelf | 校正仅支持本人 |
| database-admin-account-reset / fixture | role=self | role=other | 本人镜像停写,仍覆盖重置他人档案 |
| home-bootstrap-reveal / guards源 | 只page | page+binder,数量仍2 | 今日星语移到独立组件,并未减少等待约束 |
| personal-report-api / birth | from(profiles) | loadSubjectBirth | 报告取当前人物资料 |
| personal-report-api / GET签名 | GET() | GET(request: Request) | 支持subject查询参数 |
| report-row-delete / fetch匹配 | url==/api/reports | startsWith(/api/reports) | 允许subject查询,旧响应复活测试仍保留 |
| secondary-page-entry / state初始化 | viewFromSnapshot(peekChartPage()) | viewMatchingSubject(subjectId) | 防暖缓存显示错人 |
| server-owned-birth-profile / synastry | select ACCOUNT_BIRTH_SELECT | loadSubjectBirth | 本人与对方共用权威解析器 |
| session-list-provider / URL | sessions仅limit | limit+subject | 当时调用readCurrentSubjectId;本轮进一步bind后捕获subjectId |
| settings-mvp-contract /菜单 | span星盘资料 | /people星盘档案并禁止旧span | 独立档案页替代已退役对话框 |
## 本轮既有断言三栏
| 范围 | 原值 | 新值 | 原因 |
|---|---|---|---|
| adopted-birth-date | 死面板 record.profile有效日期 | /people selected.profile有效日期 | 保留日期正确性,转锁实际入口 |
| chart-library-other-profile:保存资格 | nextProfile | draft+保存中守卫 | 新人物页独立保存不依赖户主校正 |
| 同文件:保存/删除失败与成功刷新 | 旧helper调用、云成功文案、deleteOtherChart catch | 人物页POST/PUT/DELETE、失败早返、invalidate+load | 不再测试不可达代码;失败不得本地伪成功 |
| 同文件:添加后合盘 | 选关系提示/用于合盘按钮 | 显式和我合盘、保存不触发合盘 | 保留显式操作语义;无人物关系字段 |
| 同文件:pending | 死按钮disabled/spinner | hook重入守卫、finally复位和既有通知 | 真实入口仍不可重入 |
| 同文件:列表 | ChartLibraryView/list返回片段/添加其他人 | editing=false、列表无form、条件ChartProfileForm、添加一个人 | 名称不删除,锁替代UI |
| 同文件:本人删除/合盘 | selfView无删除、死面板历史 | 本人不能删、self新对话、绑定删除确认id | 真实详情操作边界 |
| settings-mvp-contract:编辑 | 旧本人saveProfile+otherSave | 账户readProfile+other独立saveOther | 移除死入口,不伪造当前不存在的本人编辑 |
| chart-page-view + session-list-provider URL | 调用时readCurrentSubjectId | bind后捕获subjectId | 账户与目录闸门先于请求 |
| session-list-provider 401 | 并行 OR状态检查 | 先account401,再sessions401 | 防跨账户预读先发请求;仍各自清理 |
| home-surface、3个Python surface集合 | chart-library-panel路径 | people/people-page路径 | 扩散半径同时检索tests/与frontend/;保留测试名 |
| test_supabase_user_data_contract | 死样式synastry-report-card/history、旧添加/用于合盘 | people-detail/pendingDelete、添加一个人/和我合盘 | 旧无入口面板退役,重定向合同不删除测试 |
| ephemeris生命周期、report-row-delete fixture | 默认无需绑定 | 显式虚构account已bind | 新ready门要求,原行为断言不弱化 |
| personal-report-worker harness | loadProfile只收userId | 收userId+subjectId,可注入真实resolver | 既有断言不变,扩展P0成功/失败路径 |
## 最终对比方法(待协调方冻结后执行)
```sh
node -v
npm test > final-tests.log 2>&1
npm run test:db > final-db.log 2>&1
./node_modules/.bin/tsc --noEmit
npm run lint
# 基线和最终日志分别提取完整TAP名称,使用集合差:基线名称 - 最终名称必须空;
# not ok 名单逐条比较:当前Node22基线空,因此最终必须空。
```
必须记录实际Linux日志路径、失败名称差集、消失名称差集、build Static及gzip;当前不宣称这几项完成。没有受控账号,不借用凭据,真人清单待产品负责人执行。
## 独立审查闭环与冻结(2026-09-25)
- 修复self worker metadata投影遗漏:唯一出生解析不变,仅self额外读取`rectification_case_id`;他人不读profiles,候选窗仍self专用。永久worker测试按真实select投影,防mock整行掩盖漏列。
- report subjectId别名与chartProfileId同传先判冲突,移除别名再入原strict schema,不放宽schema。永久测试覆盖别名单传、两者同值成功、冲突拒绝和未知字段仍拒绝。
- 标准`?new=1`两个bootstrap新建分支改用已绑定当前人物;合盘特殊self独立,不改变全局人物。永久bootstrap行为测试覆盖。
- A人物分页晚回不得覆盖B cursor,scope+generation同时守卫提交/错误/finally;永久React hook测试重放原竞态。
- provider用稳定初始ready避免重复bootstrap,但提供`waitUntilReady`等待当前reload代;Home调用当前gate。非401目录失败作为可恢复错误,不假登出。永久provider+bootstrap行为测试分别覆盖reload等待和目录503。
- reports/ephemeris共享cache按account+subject隔离,过期异步结果拒写;页面同scope拒晚响应。常规登出是硬导航,跨账号函数级探针不夸大为普通用户路径P0。
- `people-refund-r4`独立真实PG矩阵六场景通过:queued、running、completed、already-released、ready待结算、running完成与删除双连接并发。原失败探针/修复后探针均保留在协调方忽略artifacts,不提交。
- 本地Node22.23.2最终生产冻结点:tsc exit0;完整lint **0 error / 127 warnings**(未顺手修无关warning);54/54 review定向、fail0;先前辅助5文件51项定向通过。日志本机临时目录`people-tsc8.txt`、`people-lint-final3.txt`、`people-review-regressions6.txt`。不同组合可能重叠,不把它们相加伪称全量。
- Linux中间r1标准DB63/63、全量3868中35fail;后续定向已修各失败组,但**中间快照不是最终验收**。冻结已通知协调方,下一次直接整合最终Linux全量和永久DB测试。未经最终fail0/名称多重集合差为空不得推。
- 新永久DB退款用例覆盖真实authenticated删除,不再只mock人物null;ready fixture遵循report_document/完成时间/hash CHECK。双连接独立验证已过,最终标准suite待协调方。
### 独立审查后既有测试三栏补充
| 文件/范围 | 原值 | 新值 | 原因 |
|---|---|---|---|
| chart-page-hook fixture | cache reset后直接挂载 | reset后绑定明确虚构账户/空others | 新目录ready闸门;原17个超时、401、429、重试和缓存断言不改 |
| report-polling-contract / loadReports取消防线 | `assert.match(centerSource, /if \(cancelled\.current\) return;/)` | `assert.equal((centerSource.match(/if \(cancelled\.current \|\| requestedSubject !== readCurrentSubjectScope\(\)\) return;/g) ?? []).length, 2)` | 成功和异常两分支均在取消或账户/人物scope变化时拒绝提交;检查两处防线,未放宽取消/轮询频率合同。原台账误写ready依赖迁移,现按HEAD实际diff更正 |
| composer-isolation 两否定断言取样 | homeSurface混入独立人物表单draft | Home+聊天相关hooks集合 | 独立编辑draft不是Home根聊天draft;无根useState/value断言不变 |
| daily-starlanguage effect切片 | 旧guard/旧deps锚点 | useEffect起点/含subjectReady的新deps | 新ready/profile guard与cleanup;1次重试、清timer、cache指纹断言保留并增强当前人物来源 |
| session-list-lifecycle fetch fixture | 只account/sessions,无目录隔离 | chart-profiles合法响应,挂载/卸载reset目录 | 真走新加载链,不预设ready;StrictMode/401/不稳定callbacks收敛断言不改 |
| session-list-provider bootstrap合同 | `await deps.sessionListReady` | `await (deps.waitForSessionList?.() ?? deps.sessionListReady)`且Home传函数 | 初始promise已resolve不能代表人物切换reload就绪;永久行为测试同时锁住 |
新测试编写时的修正不伪装旧基线变更:首次新bootstrap成功测试误以为hydrated=true,按既有正常两阶段揭幕模型改锁phase=prepare+正确account;新pagination探针去掉any并指定hook类型;新增DB ready fixture补齐既有CHECK,均非放宽既有断言。
### 交付文件边界
交付包含本树tracked修改/删除、3个新增lib(worker-subject、report-subject-request、subject-session-merge)、两份新迁移、两份新people测试、进度及委托补齐docs。所有`artifacts/*`复现脚本/日志和`frontend/node_modules`junction不进提交。无commit/push、无真实账号凭据、无生产变更。