# PROGRESS · 上游同步第四轮(2026-10-02) - 任务书:`docs/tasks/TASK-upstream-sync4-20261002.md`(`origin/staging` `a18f8d4e`);吸收 `TASK-yoga-lunar-node-consistency-20261002.md`(T5)。 - 执行方式:产品负责人要求子代理直接执行。Claude(PM)已按产品授权先移植 5 项上游代码(各一提交),子代理完成其余各项、测试、评测、回测与记录。只 commit,未 push。 - 分支 / worktree:`codex/upstream-sync4-20261002` / `.worktrees/upstream-sync4-20261002`,基线 `a18f8d4e`。 - 上游参照:`/workspace/yinduzhanxing` `origin/main` `0a6696c5`(只读,未复制上游文案)。 - BUG 编号:开工核对 `origin/staging` 最大号 BUG-1182;本单 BUG-1183~1191。 ## 追加决策(产品 2026-10-02,任务书之后) - **F3 本分支一起修**:太阳 Shadbala 最低要求 5.0 → 6.5 Rupa(BPHS 第 27 章第 32–33 颂,390 Virupa)。原任务书 §3 决策 5 与 §7 写「不在本单」,以本条为准。 ## 提交 | 提交 | 内容 | BUG | | --- | --- | --- | | `42d1582f`(PM) | T2 双重过运相位 1 起数 + 新测试 | 1185 | | `f3ed9509`(PM) | T5 月亮 / 太阳类格局只计五星、Kemadruma 不计罗计、6 条重复规则退役 + 测试 | 1187 | | `96767418`(PM) | T4 格局列表不截断、按「是 list」取 | 1186 | | `08376cf0`(PM) | T3 Shadbala 四处修正 + 4 条上游测试;存档 Kala 测试三栏 | 1188 | | `bc9b9f89`(PM) | T7 定位星循环、概率改 None | 1191 | | `ba97fd59` | T1 婚姻计数只留几何指数;Parivartana 崩溃与误判 | 1183、1184 | | `3522e85d` | T4 回归测试 | 1186 | | `db55aef1` | T6 AL / UL 只留 jaimini 一个来源 | 1190 | | `09c0efc2` | F3 太阳最低要求 6.5 | 1189 | | `0a4e6d0a` | T5 补回丢掉的英文组合文字;Kemadruma 文字;节点测试 | 1187 | | `0176cb30` | V.P. Jain 基准与双重过运 golden 三栏更新 | 1185、1188 | | `db5a0509` | 双重过运结果按名字排序(哈希顺序);跨层测试三栏 | 1185 | | `5731b0af` | 研究记录按 ERR-110 重新冻结(不升算法版本) | 1188、1189 | | `79efaf83` | 普通对话两份 golden 重生成 | — | | `8ae4cef7` | 婚姻卡去掉第 7 宫「(对宫主)」重复行,守 12,000 字符预算 | 1185 | | `26d4c204` | 确认门测试读新冻结记录 | — | | `b53f56b6` | 新测试 ruff 修整 | — | | (本提交) | 记录:BUG 历史、CHANGELOG、本文件、任务索引、回测第六轮 | — | ## T1 婚姻计数(BUG-1183 / 1184) - 改动:`_interpret_marriage_count` 只写「关系几何指数 N:……不代表婚姻或关系的次数」与同星座 / 对冲两句位置描述;`_marriage_recommendations` 对所有指数给同一套三句中性说明;`note` 改几何口径;新增 `geometric_index`(`marriage_count` 兼容保留)。`_derived_marriage_evidence` 一律 `neutral`,details 只有 `geometric_index`。裁决「对象筛选」轴原来读 `details.d9_marriage_quality.quality_rating`,details 不再带它,这一行读法一并删除(多余入口删除)。 - 顺带修复(BUG-1184):距离在 Parivartana 段之前算出(旧代码有交换时 `UnboundLocalError`,模块缺失);互换判定改为「定位星落在 7 宫主掌管的星座」(旧判定实际是合相)。合相与定位星在一般盘里不罕见,旧代码在这类盘上整个模块丢失。 - 验收:`rg "再婚|段关系|第一段|终身关系|忠诚度" scripts/marriage_counting.py` 无命中。个人报告:`scripts/pl9_reader_export.py` 不渲染婚姻计数;全读的 PL9 导出包原样带 `modules.marriage_counting`,文字已是中性。 - **模型视图实测**:虚构盘 1990-06-15 10:30 北京,`/api/consultation_workflow` 婚恋路由(研究 runner 同一 handler,VedAstro 拦截)→ 婚恋主题证据 5 条(D1-7th-house、Spouse-status-yoga、DK-UL-Dasha timing、Romantic-activation、Relationship-formation),来源 `reused_chart_modules`、`full_reading_used: false`,**婚姻计数条目不出现**;经 `scripts/research/project_consult_model_context.ts`(`toModelOutput`)投影后的模型视图里也没有「Marriage-counting」「关系几何指数」。条目只在 `/api/thematic_report`(走全读)出现,已由新测试锁 `neutral` 与几何口径。 - 遗留(待产品):`_assess_d9_marriage_quality` 的评级文字(「婚姻稳定」「强烈建议婚前咨询」等)仍在全读原始模块与 PL9 导出包里,不进证据条目;是否同样只留结构事实,任务书未授权,未改。 ## T2 双重过运(BUG-1185) - 移植一行 `+ 1` 后,D1 / 月亮上升 golden(三张公开 AA 盘 × 12 宫)用测试自带 `--capture` 重采:578 个叶子条目里 413 个变化,36 行统计全部变化,同层双重过运 D1 0 → 15 处、CL 0 → 6 处。 - 重采后发现:同层重叠第一次出现,而 `cmd_double_transit_pac` 的重叠与跨层循环遍历集合,结果顺序随 `PYTHONHASHSEED` 变(seed 1、2 下 golden 测试失败,seed 3 通过)。五处循环改为排序遍历后重采,seed 0/1/2/5 都通过。 - `tests/test_double_transit_cross_layer_pairing.py` 三栏: | 断言 | 原值 | 新值 | 原因 | | --- | --- | --- | --- | | 乔布斯 7 宫摘要 | 「⚠️ 跨层间接」开头 | 「⚠️ D1 层 Double Transit 激活」开头 | 木星 9 宫相位落到 D1 7 宫,D1 层自身成立,摘要 D1 优先;跨层条目仍在 | | 第 9 宫不与无关 D9 目标配对 | 泰勒 9 宫(木星在 D1 9宫、土星在 Mars_D9) | 乔布斯 9 宫(土星在 D1 9宫、木星在 Mercury_D9) | 相位修正后泰勒那组命中不同时出现;换同结构公开盘,断言不变 | | 同宫命中集合 | 泰勒 6、12;乔布斯 2、6、7 | 奥巴马 12;泰勒 3、5、7、9、11;乔布斯 1、3、5、7 | 相位从 1 数,命中宫整体平移 | - BUG-1060 / 1061 为何没拦住:那两次只核对目标取值与跨层配对,D1 / CL golden 是在错误相位下采的,把错一宫锁成了标准答案。 - 数据卡:婚姻卡第 7 宫行因修正而增多,泰勒婚姻轮模型视图 11,984 → 12,040,超出 12,000 字符预算(`consult-condensed-checklist-20260927` size)。第 7 宫的事件宫主与对宫主是同一颗星,每个命中都重复两行;卡改为保留「(宫主)」行、去掉其「(对宫主)」重复行(卡上只放引擎原值,「nothing rewritten」合同仍成立),预算断言未改(BUG-1155 先例)。`consult-evidence-card-v2-20260927` 的 house_7 断言三栏写在测试注释。乔布斯婚姻轮 11,980,距预算 20 字,下次往卡上加字段需先看这一格。 ## T3 Shadbala(BUG-1188)与 F3(BUG-1189) - 可达路径:全读 `modules.shadbala`(报告、星盘页、数据卡 `shadbala.<星>.level`)都经 `scripts/shadbala.py` `calc_shadbala`;生时校正打分只用 `shadbala_sthana_drik_naisargika_*` 规则(`scripts/rectification/scoring_service.py`),T3 改的是 Kala / Chesta,F3 改的是最低要求,都不进打分。 - F3 位置:`scripts/shadbala.py` `MIN_REQUIRED` 是我方代码里**唯一**一张最低要求表;同文件 `MIN_REQUIRED.get(pname, 5.0)` 的 5.0 是未知天体默认值,不是 BPHS 表;`references/open_source_sources/jyotishganit/.../constants.py` `MIN_REQUIRED_SHADBALA` 与 `references/open_source_sources/dashaflow/shadbala.py` `REQUIRED_SHADBALA` 是 vendored 参照,已是 6.5,未动。代码注释引原颂。**上游 `0a6696c5` 仍是 5.0,需告知上游。** - 两张虚构盘改前(`a18f8d4e`)/ 改后(T3 + F3),Rupa、排名、Kala、Chesta、达标百分比 / 档: 盘 A(1990-06-15 10:30 北京,lahiri):排名 日 水 金 木 土 火 月 → 日 水 木 金 土 火 月 | 星 | Rupa 前 → 后 | 排名 | Kala | Chesta | 达标 / 档 | | --- | --- | --- | --- | --- | --- | | 太阳 | 10.99 → 10.99 | 1 → 1 | 205.42 → 205.42 | 119.58 → 119.58 | 219.7% 极强 → 169.0% 极强 | | 月亮 | 5.25 → 5.25 | 7 → 7 | 12.74 → 12.74 | −50.9 → −50.9 | 87.5% 略弱 → 不变 | | 火星 | 5.37 → 6.56 | 6 → 6 | 7.83 → 78.69 | 31.39 → 31.61 | 107.5% 充足 → 131.1% 强 | | 水星 | 9.40 → 9.38 | 2 → 2 | 不变 | 16.23 → 15.12 | 134.2% → 134.0% 强 | | 木星 | 8.97 → 8.97 | 4 → 3 | 不变 | 8.29 → 7.99 | 138.0% → 137.9% 强 | | 金星 | 9.37 → 8.37 | 3 → 4 | 293.83 → 233.83 | 21.08 → 20.74 | 170.4% → 152.1% 极强 | | 土星 | 6.70 → 6.70 | 5 → 5 | 不变 | 50.63 → 50.93 | 134.0% → 134.1% 强 | 盘 B(1985-03-10 04:00 上海,lahiri):排名 火 日 金 土 木 水 月 → 火 金 日 土 木 水 月 | 星 | Rupa 前 → 后 | 排名 | Kala | Chesta | 达标 / 档 | | --- | --- | --- | --- | --- | --- | | 太阳 | 7.56 → 7.56 | 2 → 3 | 不变 | 不变 | 151.1% 极强 → 116.3% 充足(F3) | | 月亮 | 5.38 → 5.38 | 7 → 7 | 不变 | 不变 | 89.7% 略弱 → 不变 | | 火星 | 9.71 → 9.67 | 1 → 1 | 不变 | 16.70 → 14.85 | 194.1% → 193.5% 极强 | | 水星 | 6.28 → 6.44 | 6 → 6 | 不变 | 18.07 → 27.28 | 89.8% → 92.0% 略弱 | | 木星 | 6.69 → 6.73 | 5 → 5 | 不变 | 10.86 → 13.27 | 102.9% → 103.5% 充足 | | 金星 | 7.19 → 7.61 | 3 → 2 | 85.87 → 107.75 | 49.61 → 52.45 | 130.8% → 138.3% 强 | | 土星 | 7.14 → 7.18 | 4 → 4 | 不变 | 36.62 → 39.10 | 142.8% → 143.6% 强 | (排名按达标百分比排,所以盘 B 太阳 Rupa 不变、F3 后排名下降。月亮 Chesta 为负是既有行为,不在本单。) - `tests/test_vp_jain_shadbala_benchmark.py` 三栏:容差内 34 → 36、变体 8 → 6;Chesta 火星 19.25 → 21.08、木星 11.23 → 8.86、土星 6.78 → 4.34 进入 ±1 Virupa,金星 27.23 → 30.03 离开(公布 28.18),水星 18.08 → 27.14 仍差 1.62。 - 名人回测 9 位的太阳档全部降一档(例:乔布斯、奥巴马、泰勒、嘉兰 充足 → 略弱;梦露、卡罗、布什、齐达内 强 → 充足;琵雅芙 略弱 → 弱)。 ## T4 格局列表(BUG-1186) - 新测试 `tests/test_api_yoga_list_presence.py`:12 条全返回;`yoga_module.yogas = []` 不回退到 `chart.yogas`;`detected_yogas` 第二、`chart.yogas` 最后。两个方法不读 handler 状态,以 unbound 方式调用,未新增 `JyotishAPIHandler.__new__`;growth contract 通过。 - 同文件其余取格局列表的 `or` 写法(未改,理由:都是补算或拼接,不是「旧预览顶替已评估结果」):`_compute_thematic_report` `yogas = full_modules.get('yoga') or collect('yogas', …)`(模块为空才补算);`enriched['yogas'] = chart.get('yogas') or []` 后再拼 `extended_yogas` / `yogas.yogas`(两段相加)。 - 数据卡:格局变多没有触发 BUG-1175 的上限;卡长变化见 T2。 ## T5 月亮 / 太阳类格局(BUG-1187) - 出处核对:BPHS 第 37 章第 7–10 颂(Sunaph / Anaph / Duradhar:「a Grah other than Sūrya」)、第 11–13 颂(Kema Drum:「Excluding Sūrya, should there be no Grah with Candr, or in the 2nd and/or 12th from Candr, or in a Kendr from Lagn」)、第 38 章第 1 颂(Vesi / Vosi / Ubhayachari:「Barring Candr, if a Grah among Mangal etc.」——明说「火星等」,即五星);B.V. Raman《Three Hundred Important Combinations》第 2–5 条。与决策 3 一致,未停。 - PyJHora 4.8.7(本机 `jhora/horoscope/chart/yoga.py`):`sunaphaa_yoga` / `anaphaa_yoga` 统计包括罗计在内的所有星,且太阳在该宫时整格不成立;`kemadruma_yoga` 用 `SUN_TO_KETU`(计罗计);`vesi_yoga` / `vosi_yoga` 同样计罗计。与经典口径不同,按决策 3 不跟。 - 退役规则(`scripts/yoga_engine.py` `RETIRED_RULE_IDS`,规则留在文件里、不参与检测):`voshi_yoga`、`veshi_yoga`、`ubhayachari_yoga`、`anapha_yoga`、`sunapha_yoga`、`durudhura_yoga`(与 `bvr_002/003/004/016/017/018` 同名重复)。上游另外 4 条退役不在本单范围,未取。 - 移植遗漏补修:PM 移植时六条 BVR 规则的 `combo_template_en` 丢了(英文版这几格没有组合说明),已补回;Kemadruma 中文 / 英文组合文字改为写明「太阳与罗计不计」。 - **与上游 Kemadruma 的差异(告知上游)**:一,上游 `kemadruma_yoga` 规则仍计罗计(`ky1` 只允许日月),我方只计五星;二,我方 `yoga_expansion.detect_kemadruma` 只看月亮 2 / 12 宫、无角宫解除,规则版看 1 / 2 / 12 宫且有「角宫只有月亮」条件,两处定义不同(角宫解除条件是占星师清单题,本单未动)。 - 卡面核对(名人回测 golden):泰勒、齐达内的格局命中只剩 Vosi / Ubhayachara,Anaphaa 不再命中,Kemadruma 不在任何一张卡上——**卡面不再同时出现 Kemadruma 与 Anaphaa**。残留:`chart.yogas` 预览(`_detect_yogas` → `detect_kemadruma`,无角宫解除)对这两张盘仍给 Kemadruma,而且同名两条(`extended` 一条、无类别一条);预览不进卡。卡罗的 Sunaphaa 由不成立变为成立(旧规则「太阳在月亮第 2 宫则整格不成立」,新规则太阳不计、有五星即成立,符合 BPHS 原文)。 ## T6 Arudha 单一来源(BUG-1190) - 可见面排查:`yogas_doshas` 的 AL / UL 在全读 `modules.yogas_doshas`(接口响应、PL9 导出包 `advanced_systems.yogas_doshas`)里原样可见;另查出两个并行来源也可见:`special_lagnas` 的 `Arudha_Lagna` / `Upapada_Lagna`(报告特殊上升点表、PL9 文字多处、`orchestrator_bridge`),过运多参考点表的 AL。数据卡(`arudha_padas.padas`)与生时校正本来就用 jaimini。 - 处理(决策 4):三处都改为取 `jaimini.calc_arudha_padas`;`yogas_doshas.calc_arudha_lagna / calc_upapada_lagna`、`special_lagnas.calculate_arudha_lagna / calculate_upapada_lagna`(及 CLI 参数)删除。jaimini 的「从源宫数」不变,上游「从落点数」未移植。 - 两张虚构盘(1990-06-15 10:30 北京;1985-03-10 04:00 上海):jaimini AL 白羊 / 处女、UL 处女 / 宝瓶;改前 `yogas_doshas` AL 狮子 / 双鱼、UL 摩羯 / 狮子,过运参考点 AL 双子 / 天秤;改后四处全等。另用 1990-06-15 00:30、02:30(命主 / 12 宫主在源宫第 4 位,旧 `special_lagnas` 例外数法会给双子而 jaimini 给射手)锁住 `special_lagnas`。 - 遗留(待产品):`special_lagnas` 的 A10(Karma Pada)仍用「从落点数」的例外,与 jaimini A10 在同类盘上不同;不在决策 4(只说 AL / UL)范围。 ## T7(BUG-1191) - PM 已移植;`rg "85-92%|75-85%|50-65%|\+15-20%" scripts` 无命中。报告 golden 无需重生成(报告模板不渲染这两处字段的变化,相关测试全过)。 ## T8 生时校正影响 - **分数没有变,不升算法版本**(决策 6 只在分数变化时升): - `tests/test_rectification_engine_memoization.py` 全文件通过;与 v2 golden 逐字段比:候选分数、决策回执全同,只有 `feature_hash` 与三个候选的 `fingerprints.shadbala` / `static` 变(Shadbala 数值变了,指纹随之变;打分只读 Sthana / Drik / Naisargika)。 - v5 77 例评测(`python3 scripts/research/holdout_v5_baseline.py --dataset v5`,`PYTHONHASHSEED=0`、缓存 TTL 0,各在一次性 worktree):`a18f8d4e`、PM 移植后 `bc9b9f89`、本分支全部引擎改动后 `0176cb30` 三次的 sweep / cluster_width / futile_collect 结果逐字节相同(合并文件只差耗时)。`0176cb30` 之后的引擎改动只有双重过运排序(`db5a0509`),不进打分。 - reported offset 900 例:0 例变化;sealed holdout 20 例:逐条相同。 - **研究记录按 ERR-110 重新冻结**:`scripts/shadbala.py` 在 dataset `frozen_scoring.files` 里,字节一变完整性门禁 13 条失败(快速门里的 `test_rectification_validation_integrity_gate.py` 等)。按先例新标签 `upstream_sync4_2026_10_02`:先 `--freeze` 再重放,`functional_v2` 记录移到 `previous_*`、逐字节保留;`references/rectification_sealed_holdout.v1.json` 更新当前身份;前端 `rectification-confirmation-gate.test.ts` 读新路径(三栏写在测试里)。 - 历史 Case 能否打开(BUG-621):本单未升算法版本、未改 Skill 版本,历史结果的身份与读取路径不变,不需要只读回退;未做浏览器级验证(无登录态),列入真机清单可选项。 - 生时校正测试:Python 全量里所有 `rectification` 相关测试与基线同名(见门禁);前端 `rectification-*` 测试全过。 | 指标(v5 77 例) | ±10 | ±30 | ±60 | | --- | --- | --- | --- | | 先验头名 前 / 后 | 0.1818 / 0.1818 | 0.0909 / 0.0909 | 0.0779 / 0.0779 | | 六题回放头名 前 / 后 | 0.6364 / 0.6364 | 0.4935 / 0.4935 | 0.3117 / 0.3117 | | 线上区间回放头名 前 / 后 | 0.6623 / 0.6623 | 0.5584 / 0.5584 | 0.4026 / 0.4026 | | 覆盖 前 / 后 | 0.987 / 0.987 | 0.987 / 0.987 | 0.987 / 0.987 | | 中位宽度(线上回放)前 / 后 | 13 / 13 | 33 / 33 | 65 / 65 | 红线 5(任一格下降 > 1 pp)未触发,不需要逐项回退复测。 ## 普通对话 golden 与回测 - `frontend/tests/fixtures/consult-evidence-card-golden.json`、`consult-biography-backtest-golden.json` 用 capture 脚本各跑两次,逐字节相同。与 `a18f8d4e` 的差异只在:格局命中与名字(T5)、双重过运结论 / 活跃宫 / 第 7 宫摘要(T2 与排序)、太阳 Shadbala 最低要求 / 百分比 / 档(F3)。 - 名人回测第六轮:`docs/testing/consult-affliction-backtest-20261001.md`「改动后(第六轮,上游同步四)」。回测跑的是排序修正之前那一版 golden(只差双重过运结论的先后顺序)与去重之前的婚姻卡(第 7 宫多一行重复),内容事实相同。 ## 门禁 | 项 | 结果 | | --- | --- | | ruff(门禁清单 5 个文件)、`py_compile scripts/*.py jyotish_vedic/*.py mcp_server.py`、隐私扫描 | 通过 | | `run_quality_gate.py --profile quick --skip-yoga-logic --skip-frontend-runtime` | failures [],exit 0 | | Python 全量(`pytest tests -n 4`) | 62 条失败,全部在开工前基线 67 条名单内;基线里 5 条 prashna 产物测试本次通过(测试自己重写 `references/oracle/prashna_*` 产物所致,产物已还原、未提交) | | `tsc --noEmit` | 0 | | `npm run lint` | 0 error(126 warning) | | `npm test` | tests 4,921(基线 4,911)、fail 24、cancelled 0;失败名单与基线 24 条逐条相同 | | `next build` | 通过,`/` 为 `○ Static`;本单改的前端代码只有服务端数据卡(`consultation-evidence-card.ts`),未量首屏 gzip | ## 上游 `0a6696c5` 之后的提交(未取,原因) | 提交 | 内容 | 未取原因 | | --- | --- | --- | | `3bc2908a`、`6f638ea2`、`4d2630ae` | 上游 API 新增「共享引擎运行合同」端点与省略输入报告 | 上游自身的 API 合同,我方产品不调用;且会给 `jyotish_api_server.py` 加处理分支(增长冻结) | | `b1d721ca` | 解读缓存失效测试 | 上游缓存机制,我方没有对应结构 | | `190c256a` | 上游阻塞优化审计文档 | 纯上游文档 | | `b40c7fde`、`28f41912` | 诅咒格局(curse yoga)健康措辞收边 + 测试 | 任务书 §7 已归「引擎硬 bug」任务书(`curse_yoga_detector` 的「过早死亡风险」措辞),不在本单 | | `acdc3551` | Narayana 默认改为「有出处约束」的 profile | 占星师清单第 2 题(Narayana 起法),任务书硬红线 3 不改 | | `197672e3` | 8 星制 Chara Karaka 罗睺度数反算 | 任务书 §7 已归「引擎硬 bug」任务书(8 星制 PiK 排位与罗睺反算) | ## 告知上游 1. 太阳 Shadbala 最低要求仍是 5.0(`scripts/shadbala.py` `MIN_REQUIRED`),BPHS 第 27 章第 32–33 颂为 390 Virupa = 6.5 Rupa。 2. `kemadruma_yoga` 规则仍计罗计;经典(BPHS 第 37 章第 11–13 颂、Raman 第 5 条)只计五星。 3. 我方 `special_lagnas` 曾与上游同为「从落点数」的 1/7 例外,已统一到 jaimini「从源宫数」(AL / UL);A10 未改。 ## 开放问题(交产品) 1. 事业「不靠曝光」类读偏:第六轮 9 / 18,第五轮 5 / 18(见回测文档);与本单改动无可证明的关联,但太阳档 9 位全降一档,建议产品下一单从卡上「落 6 / 8 / 12」字段着手(第五轮读出来的第 2 条)。 2. D9 婚姻质量评级文字是否也只留结构事实(T1 遗留)。 3. `special_lagnas` A10 的例外数法(T6 遗留)。 4. 两套 Kemadruma 定义(预览无角宫解除、规则有)与预览里同名两条(T5 遗留)。 5. 乔布斯婚姻轮模型视图 11,980 / 12,000(T2)。