Files
Jyotisha/docs/tasks/PROGRESS-consult-gender-optional-20260927.md
T

8.9 KiB
Raw Blame History

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(已含数据卡 v2 5671039a 与 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 给 authenticated UPDATE、service_role SELECT/INSERT/UPDATE(账户 PATCH 走服务角色,BUG-600 教训),chart_profiles 给 authenticated INSERT/UPDATE;两表 SELECT 本来就是表级授权 + 仅本人 RLS。admin_runtime 不授权(与 birth_date 同级)。
  • 为什么对已部署代码向后兼容:旧代码从不 select / 写 gender,旧的人物插入列集照样成功、新列留空;回滚应用后列闲置。
  • 读写位置:
    • 本人:PATCH /api/account 接受 gender(zod enum(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_role SELECT 授权,按 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,但服务角色对这张表没有任何权限(20260718100000 revoke 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 的修法决定。