Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
9.8 KiB
PROGRESS · 星盘资料加「性别(选填)」(2026-09-27)
任务书:docs/tasks/TASK-consult-gender-optional-20260927.md。执行:Claude 子代理(产品授权直接执行)。分支 codex/consult-gender-optional-20260927,工作树 .worktrees/consult-gender-optional-20260927。未推送、未部署。
基线
- 开工基线
origin/staging=7a06aa00(已含数据卡 v25671039a与 BUG-1060)。之后 staging 只多了一条纯文档提交dd85d996(BUG_HISTORY 三行),与本分支合并无冲突。 - 基线实测(Node 22.14,独立基线工作树):前端 4174 条 / 24 失败 / 28 跳过(24 条均为无 Docker 的 DB / 部署套件);Python 门禁集全绿(1 跳过);
next build --webpack后/、/chart、/ephemeris、/people均 ○ Static;首屏 rootMainFiles gzip(9) 660,412 字节。
提交
| 任务 | 提交 | 内容 |
|---|---|---|
| T1 数据层 | b912f63c |
迁移 20260927010000_profile_gender.sql;账户 GET/PATCH、人物 POST/PUT/GET、主体解析、普通对话路由带上各自的性别;DB 测试 |
| BUG-1062 | 3abae68f |
迁移 20260927020000_profile_adopted_birth_service_role_select.sql + 静态合同;BUG-1062 / BUG-1063 记录 |
| T3 婚恋卡 | 228ada22 |
数据卡婚恋段 gender = 当前人物的值;精简清单按有无切换;方法论缓存按性别分键 |
| T2 界面 | 53c657a8 |
人物编辑表单与「设置 → 个人资料」的选填单选;详情显示;DESIGN / VOICE;截图 |
| T4 记录 | 本提交 | CHANGELOG、本文件、真机清单、任务索引、BLOCKED |
T1 数据层
- 取值:存
female/male,不填 =null(界面显示女 / 男 / 不填;与ayanamsa一样用英文键存)。 - 迁移只做加法:
profiles.gender、chart_profiles.gender两列可空、无默认、无回填;CHECK 只约束新列(gender is null or gender in ('female','male'));列授权照邻近出生列:profiles给 authenticatedUPDATE、service_roleSELECT/INSERT/UPDATE(账户 PATCH 走服务角色,BUG-600 教训),chart_profiles给 authenticatedINSERT/UPDATE;两表 SELECT 本来就是表级授权 + 仅本人 RLS。admin_runtime 不授权(与 birth_date 同级)。 - 为什么对已部署代码向后兼容:旧代码从不 select / 写
gender,旧的人物插入列集照样成功、新列留空;回滚应用后列闲置。 - 读写位置:
- 本人:
PATCH /api/account接受gender(zodenum(female, male).nullable().optional(),strict schema 其他值 400);GET /api/account返回;普通对话路由loadProfile选列加gender。 - 他人:
parseChartSubjectWrite只有请求里带了gender键才写这一列(不认识这个字段的调用方不会把它清掉),null/""清空,非法值 400;jsonb 回滚镜像不放性别;libraryProfileFromSubjectRow、CHART_SUBJECT_SELECT/CHART_SUBJECT_API_SELECT带上。 - 主体解析:
chartProfileToConsultationRow、resolveSubjectBirth(他人 accountRow)带各自的值;ServerChartConsultation.gender取当前主体,不进toolInput(引擎收不到)。 - 前端
Profile.gender?、readProfile只在有值时带出。
- 本人:
ACCOUNT_BIRTH_SELECT未加gender(报告、星盘、星历等不需要,缩小影响面)。
BUG-1062(开工时顺带查出,在本单关键路径上)
- 本人性别走
PATCH /api/account,这条路由用服务角色读profiles。用迁移全集静态比对:PATCH 与ACCOUNT_BIRTH_SELECT读取的列里,active_birth_date / active_birth_timezone_offset / active_birth_provenance(20260920020000加的)没有任何 service_roleSELECT授权,按 BUG-600 的机理会 42501 → 500。本机无 Docker,未在真实库复现,状态写 investigating。 - 修复:补 SELECT 授权(只读、幂等);新增静态合同
profile-service-role-grants-20260927.test.ts(去掉新迁移时红、加回后绿)。database-profile-gender.test.ts第二条在真实 PostgreSQL 上走 PATCH,门禁 DB job 会顺带证实。这是任务书外的改动,单独一个提交,验收方可按需拆出。 - BUG-1063:他人报告 worker 用服务角色读
chart_profiles,但服务角色对这张表没有任何权限(20260718100000revoke all 后没授回)。授权范围需要决定,本轮只记录。
T3 婚恋卡
buildEvidenceCard(sources, { gender }):婚恋段gender= 「女」/「男」,没填 = 「性别未知」(规格位genderUnknown改名gender,只有婚恋段有)。标签仍是卡片唯一自写字符串(EVIDENCE_CARD_LABELS加genderFemale/genderMale)。- 精简清单:
condensedConsultationChecklist(domain, { gender })只替换那一行。填了时按strict-workflow-router.md§4「先确认性别与昼夜盘」与仓内references/oracle/gender_interpretation_contract_2026_07_19.json:女 = 夫星以木星为主、部分传承兼看火星;男 = 妻星取金星;都只作补充,核心仍是 7 宫、7 宫主、D9、UL、DK,不得只因配偶星的大运 / 过运定婚期。行数不变(7 行)。 consultationMethodologyForDomains(domains, { gender })的缓存键加上性别——否则第一位用户的清单会被缓存后发给下一位(测试覆盖了这条)。- 系统提示里旧句「If gender … is present in future profile context」改为指向数据卡的 gender 字段(
src/mastra/index.ts一行,内容规则不变)。 - 遥测只记字段 id,测试确认性别值不进遥测、不算引用字段。
- 测试(真实
getJyotishAgent+ 记录提示词的假模型,golden 引擎数据):填女 / 男 → 卡上有性别、清单无「性别未知」;不填 / null → 相反;同一进程依次跑 本人(女) → 他人(未填) → 他人(男) → 本人(女),每轮取当轮人物的值(经prepareConsultationRoute真实解析,本人是女时他人未填仍是「性别未知」)。
T2 界面
- 一个组件
ProfileGenderField(女 / 男 / 不填,44px,一行说明),两处用:- 星盘档案编辑表单(出生地点之后、岁差之前),随「保存」提交,「不填」写显式
null以便清空。 - 「设置 → 个人资料」(本人唯一入口):选中即单独 PATCH
{gender},显示「已保存。」,保存中禁用、无 spinner。出生资料保存(persistProfile,含开场)不带性别,不会误清。
- 星盘档案编辑表单(出生地点之后、岁差之前),随「保存」提交,「不填」写显式
- 详情卡加「性别」行(没填「未填」);本人下面一行灰字「在「设置 → 个人资料」里改」,本页不给本人第二个入口(产品偏好:少入口)。
- 开场 / 注册不问(测试锁住
home-onboarding-shell.tsx不含性别)。 page.tsx:只多解构一个persistGender并传给ProfilePanel(+1 行,useState / useRef 数不变)。- 截图(本地
next build --webpack+next start+ Chrome 无头,临时 harness 页渲染真实组件与虚构人物,harness 未提交):docs/testing/consult-gender-optional-20260927/下 390 与 1280 各 4 张(他人详情、本人详情、编辑表单、个人资料选中「女」后)。CDP 检查:无横向溢出,性别按钮全部 ≥44px,点「不填」后草稿跟着变,个人资料点选后出现「已保存。」。
既有断言变更
无。既有测试文件只改了 tests/consult-natal-agent-test-support.ts:runNatalAgent 加可选 serverChart 参数(默认值不变),没有改任何断言。
验收数据(交付 HEAD,Node 22.14)
| 项 | 基线 7a06aa00 |
交付 |
|---|---|---|
tsc --noEmit |
— | 0 错 |
npm run lint |
— | 0 error |
| 前端全量 | 4174 / 24 fail / 28 skip | 4192 / 24 fail / 30 skip |
| 失败名单 | 24 条 DB/部署 | 与基线逐条一致;消失的测试名 0;新增 18 条(2 条 DB 在本机 skip) |
| Python 门禁集(含 growth contract) | 全绿,1 skip | 全绿,1 skip |
next build --webpack |
/ /chart /ephemeris /people ○ Static |
同 |
| 首屏 rootMainFiles gzip(9) | 660,412 B | 661,444 B(+0.16%) |
环境缺口
- 无 Docker:
npm run test:db未跑。新增frontend/tests/database-profile-gender.test.ts(列形状、CHECK、RLS 本人可读写 / 他人不可见不可改、旧插入列集照样成功、service_role 写、admin_runtime 无权;真实路由 POST/PUT/GET 人物与 PATCH 账户、陌生人 404 / 列表为空),本机两条 skip,结果以门禁 DB job 为准,run 号待推送后补记,不得写成已通过。 - 无登录态与模型凭据:婚恋回答是否真的按性别取夫星 / 妻星,按
docs/testing/consult-gender-optional-20260927.md部署后真机走。 - Skill 文本未改(SKILL.md 基础段描述加 D9 摘要 / 性别字段一项不是必须,本轮不做,不 bump)。
未做 / 留给验收方
- 推送、部署、门禁 run 号。
- BUG-1063 的修法决定。
验收(Claude,2026-09-27)
rebase 到 dd85d996 后独立复跑(Node 22.14,顺序执行):tsc 0;lint 0 error;npm test 4192 / 24 fail / 0 cancelled / 30 skip,失败名单与 BUG-1060 分支基线逐条一致、无消失测试名(新增 2 条 DB 测试本机跳过);Python 门禁集退出 0;/、/chart、/ephemeris、/people ○ Static;rootMainFiles gzip(level 9)130933 B。迁移只加可空列 + CHECK + 列级授权,对已部署代码向后兼容;BUG-1062 补丁只加 service_role 列级 SELECT(我核对了 20260920020000 确实未授予)。截图核对:编辑表单「性别(选填)」三选一 + 一句说明。
待门禁:database-profile-gender.test.ts 与 profile-service-role-grants 的真实库结果以本次推送的门禁 DB job 为准(run 号补记)。BUG-1063(报告 worker 以 service_role 读 chart_profiles 无授权)待产品/安全决定。