diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a213016..f51751c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,10 @@ ## 2026-11-05 — #166 占星师 11-05 答复:待核口径加标签,严格 Gajakesari 不再把凶性水星算作吉星支持,新增 PVR 双宫主 Arudha 对照 -- Shadbala 结果的 `method_variants` 写明两项尚待占星师核定的口径:七分盘尊位力本垣 45 分暂只在 D1 按度数段计(`saptavargaja_moolatrikona`),水星、木星相照暂按四分之一计(`drik_mercury_jupiter`);水星自然吉凶口径改名,写明不计交点是本站的实现选择、亏月计入。数值都不变(BUG-1613、BUG-1614)。 -- 分盘里按分盘内度数判本垣(全读 D9 表、咨询 D9 摘要)标为待核;此前文档里的「V.P. Jain 例题」更正为 PyJHora 测试转录的夹具(BUG-1613)。 -- Gajakesari 严格定义:与太阳、火星、土星或亏月同座的水星不再算作吉星支持,与 Shadbala 用同一条规则(BUG-1615)。Matrunasa 199 的效果文字改为它自己的条件,198 写明凶星集合、交点不给相照是保守口径(BUG-1616)。 -- 新增天蝎 / 水瓶 Arudha 的 PVR 双宫主比较,只作参考,不进默认 A10 / AL / UL、星盘页和生时校正(BUG-1617)。 +- Shadbala 结果的 `method_variants` 写明两项尚待占星师核定的口径:七分盘尊位力本垣 45 分暂只在 D1 按度数段计(`saptavargaja_moolatrikona`),水星、木星相照暂按四分之一计(`drik_mercury_jupiter`);水星自然吉凶口径改名,写明不计交点是本站的实现选择、亏月计入。数值都不变(BUG-1622、BUG-1623)。 +- 分盘里按分盘内度数判本垣(全读 D9 表、咨询 D9 摘要)标为待核;此前文档里的「V.P. Jain 例题」更正为 PyJHora 测试转录的夹具(BUG-1622)。 +- Gajakesari 严格定义:与太阳、火星、土星或亏月同座的水星不再算作吉星支持,与 Shadbala 用同一条规则(BUG-1624)。Matrunasa 199 的效果文字改为它自己的条件,198 写明凶星集合、交点不给相照是保守口径(BUG-1625)。 +- 新增天蝎 / 水瓶 Arudha 的 PVR 双宫主比较,只作参考,不进默认 A10 / AL / UL、星盘页和生时校正(BUG-1626)。 - 生时校正分数不变(仍为 scoring-15);冻结记录按 ERR-110 更新为 `astrologer_166c_2026_11_05`,密封 20 例与报时 900 次回放逐条相同。Skill 版本不变;没有数据库迁移。 ## 2026-11-04 — #166 第 9 条:Narayana 大运默认改用 Sanjay Rath 版 diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 1831123c..0f287fcf 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -22075,7 +22075,7 @@ - 复发自:无 - 修复版本:分支 `feat/global-boot-loader`。 -## BUG-1613 | 七分盘尊位力的本垣 45 分「只在 D1、只按度数段」被当作 BPHS 定案;「V.P. Jain 例题」实为 PyJHora 测试转录 +## BUG-1622 | 七分盘尊位力的本垣 45 分「只在 D1、只按度数段」被当作 BPHS 定案;「V.P. Jain 例题」实为 PyJHora 测试转录 - 状态:resolved(只加标签、注释与测试,数值不变;未部署) - 首次发现 / 最近更新:2026-11-05(#166 占星师答复,Gitea #166 评论 39249 第 1 项,对应 39236 第 1 项、问题清单第 17 / 19 条)/ 2026-11-05 @@ -22085,13 +22085,13 @@ - 根因:Santhanam 版 27.2–4(印刷页 265)确认本垣 45 分,并说同样的值适用于其余六个分盘;「只在 D1」不是这段译文写明的例外,D1 整座还是度数段、其他六盘怎么计(分盘星座还是分盘内度数、D30 如何换算)都没有解决。现行实现是临时选择,却没有标出。V.P. Jain 一项来自 PyJHora `pvr_tests.py::shadbala_VPJainBook_tests`,没有书名、版本和原页(ERR-081 已记过,数据核对文档又写成了「例题」)。 - 修复:`SAPTAVARGAJA_MOOLATRIKONA_CONVENTION = "d1_degree_band_only_provisional"`,写进 `method_variants.saptavargaja_moolatrikona`,注释写明是临时实现、待核,不是 BPHS 定案;`jyotish_engine.VARGA_MOOLATRIKONA_BASIS = "in_varga_degree_band_pending_review"`,D9 扩展表每行加 `moolatrikona_basis`,咨询 D9 摘要加同名字段(数据卡不复制这个字段)。三处数据核对 / 竞品文档把「例题 / 书例」改为「PyJHora 测试转录的夹具」并注明更正。`astrologer_questions.md` 末尾加 2026-11-05 七项落地状态表。没有改任何计算。 - 验证:`tests/test_astrologer_rulings_166c.py`:标签值、`method_variants` 输出、D1 度数段内 45 / 段外 30、其他六盘从不得 45(行为未变)、D9 摘要标签且狮子 25° 太阳仍判自有星座;`test_shadbala_service_api.py` 期望的 `method_variants` 加两项(原值 / 新值 / 原因注释)。 -- 冻结身份(ERR-110,本轮全部 shadbala.py 改动一次重冻):`shadbala.py` 在冻结身份里(holdout_v3 `frozen_scoring.files` 与扩展身份)。本轮所有 shadbala.py 改动(BUG-1613、BUG-1614 的标签,BUG-1615 共用的水星规则函数)放在同一提交 `5ffef30a`;在本分支全部代码提交之后(`09fd3a42`)按 ERR-110 改 FREEZE / REPORT 常量、`--freeze` 后回放,标签 `astrologer_166c_2026_11_05`,合同轮换,上一份 `astrologer_166b_2026_11_04` 逐字节保留。校正身份仍是 `rectification-v5-matrix-scoring-15`,没有升 ALGORITHM_VERSION。与 `astrologer_166b_2026_11_04` 逐条逐字段比:密封 20 条全同,`metrics` 不变(头名率 0.40、前三率 0.45、平均分钟误差 6.95);报时 900 条全同,`summary` 不变(±15 / 30 / 60 头名命中 4 / 3 / 0,前三 31 / 34 / 30,±15 交付覆盖 219,头名平均分钟误差 20.52)。相对 09-20 历史报告 changed_trial_count:密封 10 / 20、报时 731 / 900,与上一份相同。未调参。重冻提交 `39d7cb5e`。`jaimini.py`、`functional_benefics.py`、`rectification/*` 没有改动。 +- 冻结身份(ERR-110,本轮全部 shadbala.py 改动一次重冻):`shadbala.py` 在冻结身份里(holdout_v3 `frozen_scoring.files` 与扩展身份)。本轮所有 shadbala.py 改动(BUG-1622、BUG-1623 的标签,BUG-1624 共用的水星规则函数)放在同一提交 `5ffef30a`;在本分支全部代码提交之后(`09fd3a42`)按 ERR-110 改 FREEZE / REPORT 常量、`--freeze` 后回放,标签 `astrologer_166c_2026_11_05`,合同轮换,上一份 `astrologer_166b_2026_11_04` 逐字节保留。校正身份仍是 `rectification-v5-matrix-scoring-15`,没有升 ALGORITHM_VERSION。与 `astrologer_166b_2026_11_04` 逐条逐字段比:密封 20 条全同,`metrics` 不变(头名率 0.40、前三率 0.45、平均分钟误差 6.95);报时 900 条全同,`summary` 不变(±15 / 30 / 60 头名命中 4 / 3 / 0,前三 31 / 34 / 30,±15 交付覆盖 219,头名平均分钟误差 20.52)。相对 09-20 历史报告 changed_trial_count:密封 10 / 20、报时 731 / 900,与上一份相同。未调参。重冻提交 `39d7cb5e`。`jaimini.py`、`functional_benefics.py`、`rectification/*` 没有改动。 - 防复发:口径名写进输出;更正处注明出处性质。引用外部数值时先写清是书页、作者教材还是软件测试夹具。 - 相关记录:BUG-1583、BUG-1584、BUG-1575、ERR-081、#166。 - 复发自:ERR-081(夹具被写成出版例题;这次出在数据核对文档里,ERR-081 只约束了基准文件的命名,没有约束研究文档的措辞) - 修复版本:分支 `codex/astrologer-166c-20261105`,`5ffef30a`、`54e654db`;重冻 `39d7cb5e`(未推送)。 -## BUG-1614 | 水星自然吉凶口径名写成「BPHS 3.11、不含交点」,Drik 水星 / 木星相照的四分之一没有标口径 +## BUG-1623 | 水星自然吉凶口径名写成「BPHS 3.11、不含交点」,Drik 水星 / 木星相照的四分之一没有标口径 - 状态:resolved(只加标签、注释与测试,数值不变;未部署) - 首次发现 / 最近更新:2026-11-05(#166 评论 39249 第 2、4、7 项,对应问题清单第 23、25、24 条)/ 2026-11-05 @@ -22099,15 +22099,15 @@ - 用户现象:`method_variants.mercury_nature = bphs_3_11_any_malefic_same_sign_no_nodes`,读起来像 BPHS 规定排除交点;Drik 里水星、木星发出的相照按四分之一计,输出没有口径;26.11–12 特殊相照只引网络英译。 - 触发条件:任何盘(标签问题)。 - 根因:Santhanam 版 3.10–11(印刷页 27)的自然凶星包含太阳、火星、土星、亏月、罗睺、计都,随后说水星与凶星结合则凶;排除罗睺、计都是本仓的实现选择(Drik 只看七星),不是 BPHS;印刷页 28 的译者注(亏月与水星结合两者皆吉)是另一层,未采用。27.19(印刷页 284)水星 / 木星相照有三种读法:全额替换四分之一(1 倍)、Santhanam 英译字面「四分之一之外再加全额」(吉性 1.25 倍;原始 40 时木星或吉性水星 +10 + 40 = +50,凶性水星若附加项仍为正则 −10 + 40 = +30,凶性水星的符号待核)、Raman 的四分之一;占星师未裁定。26.11–12 已由占星师对照 Santhanam 印刷页 256 确认(火星 [180, 210) 为 60,木星 [120, 150)、[240, 270) 为 60 − 段内度数),左闭右开是工程约定。 -- 修复:`MERCURY_NATURE_CONVENTION` 改名为 `same_sign_any_natural_malefic_waning_moon_included_nodes_excluded_implementation_choice`(原值 / 新值 / 原因注释),行为不变;规则抽成唯一实现 `mercury_malefic_companions()`,`classify_drik_planets` 调用它(BUG-1615 的严格 Gajakesari 也调用它)。`DRIK_MERCURY_JUPITER_CONVENTION = "quarter_only_raman_pending"` 写进 `method_variants.drik_mercury_jupiter`,注释列三种读法与 40 的算例;本轮不加附加法。`_sphuta_drishti_virupas` 注释补 Santhanam 印刷页 256 与端点约定。 +- 修复:`MERCURY_NATURE_CONVENTION` 改名为 `same_sign_any_natural_malefic_waning_moon_included_nodes_excluded_implementation_choice`(原值 / 新值 / 原因注释),行为不变;规则抽成唯一实现 `mercury_malefic_companions()`,`classify_drik_planets` 调用它(BUG-1624 的严格 Gajakesari 也调用它)。`DRIK_MERCURY_JUPITER_CONVENTION = "quarter_only_raman_pending"` 写进 `method_variants.drik_mercury_jupiter`,注释列三种读法与 40 的算例;本轮不加附加法。`_sphuta_drishti_virupas` 注释补 Santhanam 印刷页 256 与端点约定。 - 验证:`tests/test_astrologer_rulings_166c.py`:亏月同座使水星为凶、盈月不使、交点不使;共用函数与 Drik 分类在 24 × 12 × 2 个位置上一致;木星 180° 相照太阳 Drik = 60 / 4 = 15;特殊相照端点 149.99 / 150 / 150.01、179.99 / 180 / 209.99 / 210 / 210.01、269.99 / 270 / 270.01,以及 `round(angle, 2)` 把 149.996 吸到 150(值 0)、149.994 仍为 30.01。`test_astrologer_rulings_166.py`、`test_shadbala_drik_deterministic.py`、`test_vp_jain_shadbala_benchmark.py` 照旧通过。 -- 冻结身份:同 BUG-1613(`astrologer_166c_2026_11_05`,回放逐条相同)。 +- 冻结身份:同 BUG-1622(`astrologer_166c_2026_11_05`,回放逐条相同)。 - 防复发:口径名不再写成来源已规定的样子;「实现选择」「待核」写进名字或注释。 - 相关记录:BUG-1585、BUG-1586、BUG-1576、#166。 - 复发自:无 - 修复版本:分支 `codex/astrologer-166c-20261105`,`5ffef30a`;重冻 `39d7cb5e`(未推送)。 -## BUG-1615 | 严格 Gajakesari 把与自然凶星同座的水星仍算作吉星支持 +## BUG-1624 | 严格 Gajakesari 把与自然凶星同座的水星仍算作吉星支持 - 状态:resolved(引擎 + 回归测试;未部署) - 首次发现 / 最近更新:2026-11-05(#166 评论 39249 第 6 项,对应 39236 第 6 项、问题清单 I 报告第 5 条)/ 2026-11-05 @@ -22117,13 +22117,13 @@ - 根因:BUG-1596 的严格定义把金星、水星无条件当吉星。PVR §11.6(印刷页 124–125,PDF 136–137)严格定义要求吉星结合或相照(二选一),三个主条件 AND;占星师:受凶影响的水星不得无条件提供吉星支持,应服从所选的自然吉凶规则。 - 修复:沙盒函数 `mercury_malefic_companions()` 懒加载并调用 `shadbala.mercury_malefic_companions`(与 Drik 同一规则、同一标签:与太阳、火星、土星或亏月同座即凶,交点不计;无循环导入),不另立规则。严格版把凶性水星从吉星支持里去掉;金星仍支持时触发项写明「水星与 X 同宫,按凶星计,不算吉星支持」。强木星变体:它判断「严格版不成立」时用同一规则,两条规则保持互斥;变体本身不用吉星支持,所以这条规则对它没有别的作用。保留并标待核:敌宫按自然友敌(不是五重友敌)、月亮不作支持星(占星师未认可)。 - 验证:`tests/test_astrologer_rulings_166c.py`:凶性水星是唯一支持时严格版不成立、只剩月木角宫关系;吉性水星仍成立;亏月同座使水星凶、严格版不成立;交点同座不影响;金星支持时写出被排除的水星;木星入旺巨蟹、唯一支持是凶性水星时严格版不成立、强木星变体成立。`test_astrologer_rulings_166_batch2.py`、`test_yoga_audit_i_20261104.py`(静态扫描:新辅助函数已在命名空间)、全部 `tests/test_yoga*.py` 通过。60 张标准测试盘(`references/planet_positions_60.json`)严格版成立 4 → 4,没有一张变;三张公开盘证据卡与 9 位名人回测捕获里没有 Gajakesari 成立,重新捕获后瑜伽输出无变化。 -- 冻结身份:yoga_engine.py、yoga_rules.json 不在冻结身份里;共用函数所在的 shadbala.py 改动见 BUG-1613 的重冻记录(回放逐条相同)。 +- 冻结身份:yoga_engine.py、yoga_rules.json 不在冻结身份里;共用函数所在的 shadbala.py 改动见 BUG-1622 的重冻记录(回放逐条相同)。 - 防复发:同一条自然吉凶规则只有一个实现,瑜伽沙盒调用它,不在规则表里重写。 -- 相关记录:BUG-1596、BUG-1614、BUG-1585、#166。 +- 相关记录:BUG-1596、BUG-1623、BUG-1585、#166。 - 复发自:无 - 修复版本:分支 `codex/astrologer-166c-20261105`,`e9ff1f61`(共用函数 `5ffef30a`)(未推送)。 -## BUG-1616 | Matrunasa 199 的效果文字写的是 198 的内容;198 的交点、凶星集合与版本页码没有标口径 +## BUG-1625 | Matrunasa 199 的效果文字写的是 198 的内容;198 的交点、凶星集合与版本页码没有标口径 - 状态:resolved(规则表文字与标签;检测不变;未部署) - 首次发现 / 最近更新:2026-11-05(#166 评论 39249 第 5 项)/ 2026-11-05 @@ -22139,7 +22139,7 @@ - 复发自:BUG-1597(拆分时漏改 199 的效果文字) - 修复版本:分支 `codex/astrologer-166c-20261105`,`8bba999f`(未推送)。 -## BUG-1617 | 天蝎 / 水瓶的 Arudha 只用固定宫主(火星、土星),没有 PVR 双宫主择强的对照 +## BUG-1626 | 天蝎 / 水瓶的 Arudha 只用固定宫主(火星、土星),没有 PVR 双宫主择强的对照 - 状态:resolved(新增参考模块,未进默认路径;未部署) - 首次发现 / 最近更新:2026-11-04(#166 第 28 条,BUG-1588 记为未实现)/ 2026-11-05(评论 39249 第 3 项) @@ -22149,7 +22149,7 @@ - 根因:只实现了固定宫主表;占星师 11-04 认为 PVR 口径 Arudha 应双主择强,但不要全系统替换,11-05 核对了比较顺序。 - 修复:`select_pvr_arudha_lord()` 按 PVR《Vedic Astrology: An Integrated Approach》§15.5.1(印刷页 201–203,PDF 213–215),前一级决出即停:1 只有一颗宫主在该星座内时取另一颗;2 同座伴星多者(不计自身,上升点不算,九曜含交点);3 木星、水星、所在星座宫主三个角色以结合或星座相照支持多者(同一星承担两个角色计两次);4 入旺;5 所在星座双体 > 固定 > 变动;6 座内度数高者,交点按 30° − 度数。完全并列、所在星座宫主又是天蝎 / 水瓶双主且递归回到自身、缺经度时返回 blocked 与原因,两颗候选都保留,不强行选一个。输出获选者或 blocked、两颗候选、决出层级、逐级 trace 与工程选择清单。工程选择(不是教材原文,待核):并列 / 递归的 blocked 处理;宫主角色由候选星自身充当时照算(与 `jaimini._co_lord_strength` 一致);交点入旺取罗睺金牛、计都天蝎。`pvr_arudha_reference()` 对天蝎 / 水瓶两宫并列给出默认 pada 与 PVR pada,pada 算法直接调用 `jaimini.calc_arudha_pada_for_house`(唯一的 Arudha 实现,含 §9.2 例外),只把宫主经度换成获选者。标签「PVR 双宫主比较(参考,未进默认)」,`in_default_paths = false`。`jaimini.py`(含 Chara 双主选择器 `_co_lord_strength`)一字未改。 - 验证:`tests/test_arudha_lord_selection_pvr.py` 16 条:第 1 级两个方向与两星都在本宫时继续;第 2 级交点计入伴星、上升点 / Ascendant 键不计;第 3 级木星同时任木星与宫主角色计 2;第 4 级入旺;第 5 级双体胜固定;第 6 级交点 30° − 度数改变胜负;完全并列 blocked;天蝎 / 水瓶互为宫主的递归 blocked;缺经度 blocked、非双主星座拒绝;参考行在获选者改变 pada 时标 `differs_from_default`、默认 pada 仍按火星;校正与默认路径的模块不引用本模块;CLI 带出参考字段且默认 `arudha_padas` 不变;`jaimini.py` 字节与冻结身份记录的 sha256 相同。 -- 冻结身份:新模块不在冻结身份里,也不被冻结文件引用;`jaimini.py` 未改。重冻(BUG-1613)回放逐条相同。占星师:「进入校正打分仍需独立验收」,本轮不接入。 +- 冻结身份:新模块不在冻结身份里,也不被冻结文件引用;`jaimini.py` 未改。重冻(BUG-1622)回放逐条相同。占星师:「进入校正打分仍需独立验收」,本轮不接入。 - 防复发:默认路径不引用本模块由测试锁住;取法逐级写进 trace,工程选择随结果输出。 - 相关记录:BUG-1588、BUG-1566、#166。 - 复发自:无 diff --git a/docs/research/data_audit_2026_11_04/astrologer_questions.md b/docs/research/data_audit_2026_11_04/astrologer_questions.md index 0b96e6b9..90d109ba 100644 --- a/docs/research/data_audit_2026_11_04/astrologer_questions.md +++ b/docs/research/data_audit_2026_11_04/astrologer_questions.md @@ -34,7 +34,7 @@ ## 五、Shadbala 位置力与相照力(J 报告,`audit_j_shadbala_sthana_dig_drik.md`) 16. 七分盘尊位力分值:Raman 22.5/7.5/3.75/1.875,还是 BPHS 27.3(梵文)20/10/4/2。 -17. D1 本垣按度数范围,还是整个星座都算(PyJHora、V.P. Jain 例题按整个星座)。〔2026-11-05 更正:「V.P. Jain 例题」实为 PyJHora 测试 `pvr_tests.py::shadbala_VPJainBook_tests` 转录的数值夹具,没有书名、版本和原页,不是书中例题(ERR-081 复发,BUG-1613)。〕 +17. D1 本垣按度数范围,还是整个星座都算(PyJHora、V.P. Jain 例题按整个星座)。〔2026-11-05 更正:「V.P. Jain 例题」实为 PyJHora 测试 `pvr_tests.py::shadbala_VPJainBook_tests` 转录的数值夹具,没有书名、版本和原页,不是书中例题(ERR-081 复发,BUG-1622)。〕 18. 月亮、水星本垣从 4°、16° 起,还是按 BPHS 从 3°、15° 起。 19. 本垣只在 D1 计,还是其他分盘也计。 20. 临时友敌取 D1,还是每张分盘各自计算。 @@ -64,14 +64,14 @@ ## 2026-11-05 占星师答复(#166 评论 39249)落地状态 -占星师说明本轮没有把七项都标成「已正式核定」。下表只记录本仓据此做了什么;「待核」的项保留现行算法,只加标签,不当作已核定的 BPHS 规则。生时校正分数不变(`astrologer_166c_2026_11_05` 重冻回放逐条相同,见 BUG-1613~1617)。 +占星师说明本轮没有把七项都标成「已正式核定」。下表只记录本仓据此做了什么;「待核」的项保留现行算法,只加标签,不当作已核定的 BPHS 规则。生时校正分数不变(`astrologer_166c_2026_11_05` 重冻回放逐条相同,见 BUG-1622~1626)。 | 39236 编号 | 对应本表 | 占星师结论 | 本仓处理 | |---|---|---|---| -| 1 | 17、19 | 45 分本版正文可确认,且译文说同值适用其余六盘;D1 整座 / 度数段、其他六盘怎么计、分盘度数与 D30 换算都待核。「V.P. Jain 例题」实为 PyJHora 测试转录的夹具 | 保留 D1 度数段,`method_variants.saptavargaja_moolatrikona = d1_degree_band_only_provisional`;D9 按分盘内度数判本垣标 `in_varga_degree_band_pending_review`;更正 V.P. Jain 出处(BUG-1613) | -| 2 | 23 | Santhanam 27.19(印刷页 284)字面是四分之一之外再加全额:吉性 1.25 倍;凶性水星的附加项符号待核;1 倍法、四分之一法各留标记 | 仍按四分之一,`method_variants.drik_mercury_jupiter = quarter_only_raman_pending`;本轮不加附加法(BUG-1614) | -| 3 | 28 | PVR §15.5.1(印刷页 201–203,PDF 213–215)六级比较可确认;上升点不算伴星;交点计入可作本教材口径;并列与递归保留两候选是工程处理;进校正打分须另行验收 | 新模块 `scripts/arudha_reference/pvr_dual_lord.py`,只作参考,不进默认 A10 / AL / UL、星盘页与校正(BUG-1617) | -| 4 | 25 | 正文自然凶星含罗睺、计都,排除交点不能称 BPHS;符合条件的亏月在集合内;印刷页 28 译注(亏月与水星结合两者皆吉)是另一层 | 行为不变,`MERCURY_NATURE_CONVENTION` 改名写明排除交点是实现选择、亏月计入;译注层未采用(BUG-1614) | -| 5 | 6(Matrunasa) | 198 三种情况为「或」;交点不给相照可暂时保留,但须标保守工程口径、待核;写明凶星集合;版本页码待核 | 检测不变,加标签;199 的效果文字原来写的是 198 的内容,已改(BUG-1616) | -| 6 | 5(Gajakesari) | 严格版:结合或相照二选一,三个主条件 AND;受凶影响的水星不得无条件算吉星支持;自然敌宫与不含月亮均待核 | 严格版不再把与自然凶星同座的水星算作支持(与第 4 项同一规则、同一函数);自然敌宫、月亮不作支持保留并标待核(BUG-1615) | -| 7 | 24 | 26.11–12 两段与 Santhanam 印刷页 256 一致;左闭右开是工程约定 | 逻辑不变,补端点 ±0.01 测试与页码出处(BUG-1614) | +| 1 | 17、19 | 45 分本版正文可确认,且译文说同值适用其余六盘;D1 整座 / 度数段、其他六盘怎么计、分盘度数与 D30 换算都待核。「V.P. Jain 例题」实为 PyJHora 测试转录的夹具 | 保留 D1 度数段,`method_variants.saptavargaja_moolatrikona = d1_degree_band_only_provisional`;D9 按分盘内度数判本垣标 `in_varga_degree_band_pending_review`;更正 V.P. Jain 出处(BUG-1622) | +| 2 | 23 | Santhanam 27.19(印刷页 284)字面是四分之一之外再加全额:吉性 1.25 倍;凶性水星的附加项符号待核;1 倍法、四分之一法各留标记 | 仍按四分之一,`method_variants.drik_mercury_jupiter = quarter_only_raman_pending`;本轮不加附加法(BUG-1623) | +| 3 | 28 | PVR §15.5.1(印刷页 201–203,PDF 213–215)六级比较可确认;上升点不算伴星;交点计入可作本教材口径;并列与递归保留两候选是工程处理;进校正打分须另行验收 | 新模块 `scripts/arudha_reference/pvr_dual_lord.py`,只作参考,不进默认 A10 / AL / UL、星盘页与校正(BUG-1626) | +| 4 | 25 | 正文自然凶星含罗睺、计都,排除交点不能称 BPHS;符合条件的亏月在集合内;印刷页 28 译注(亏月与水星结合两者皆吉)是另一层 | 行为不变,`MERCURY_NATURE_CONVENTION` 改名写明排除交点是实现选择、亏月计入;译注层未采用(BUG-1623) | +| 5 | 6(Matrunasa) | 198 三种情况为「或」;交点不给相照可暂时保留,但须标保守工程口径、待核;写明凶星集合;版本页码待核 | 检测不变,加标签;199 的效果文字原来写的是 198 的内容,已改(BUG-1625) | +| 6 | 5(Gajakesari) | 严格版:结合或相照二选一,三个主条件 AND;受凶影响的水星不得无条件算吉星支持;自然敌宫与不含月亮均待核 | 严格版不再把与自然凶星同座的水星算作支持(与第 4 项同一规则、同一函数);自然敌宫、月亮不作支持保留并标待核(BUG-1624) | +| 7 | 24 | 26.11–12 两段与 Santhanam 印刷页 256 一致;左闭右开是工程约定 | 逻辑不变,补端点 ±0.01 测试与页码出处(BUG-1623) | diff --git a/docs/research/data_audit_2026_11_04/audit_j_shadbala_sthana_dig_drik.md b/docs/research/data_audit_2026_11_04/audit_j_shadbala_sthana_dig_drik.md index 3a5d7fdf..8395b387 100644 --- a/docs/research/data_audit_2026_11_04/audit_j_shadbala_sthana_dig_drik.md +++ b/docs/research/data_audit_2026_11_04/audit_j_shadbala_sthana_dig_drik.md @@ -40,7 +40,7 @@ | Uchcha | 到落陷点的弧折回 0–180°,再除以 3 | BPHS 27.1;Raman §20 与例 3、例 13 | 无(PyJHora 140/140,jyotishganit 140/140) | 正确 | | Saptavargaja:七个分盘 | D1、D2(Parashara Hora)、D3(1-5-9)、D7、D9、D12、D30(Parashara) | BPHS 27 序言;Raman 例 6 | jyotishganit 138/140 | jyotishganit 的错:D2、D3、D7、D12、D30 用循环 Dn,不是 Parashara 分法;自然友敌查表恒返回 SAMA(`get_natural_relationship` 查的是 'friends' 等键,对行星名查不到);根本三角常量错(月亮巨蟹、金星金牛、土星摩羯);暂时友敌拿行星的分盘星座去比宫主的本命星座 | | Saptavargaja:分值 | 45 / 30 / 22.5 / 15 / 7.5 / 3.75 / 1.875 | Raman §30(第 22–23 页),沿用 Sripati;例 9 太阳 90.000 | BPHS 27.2–3、saravali 用 45 / 30 / 20 / 15 / 10 / 4 / 2 | **具名流派差 V1** | -| Saptavargaja:本命盘根本三角 | 按度数范围(太阳狮子 0–20° 等) | BPHS 3.51–54:「the rest is his own Bhava」 | PyJHora 与 VP Jain 夹具按整个星座(5/140;VP Jain 太阳、水星各 −15)〔2026-11-05 更正:原写「例题」;这是 PyJHora 测试转录的数值夹具,不是带书名页码的书中例题,BUG-1613〕 | **流派差 V2** | +| Saptavargaja:本命盘根本三角 | 按度数范围(太阳狮子 0–20° 等) | BPHS 3.51–54:「the rest is his own Bhava」 | PyJHora 与 VP Jain 夹具按整个星座(5/140;VP Jain 太阳、水星各 −15)〔2026-11-05 更正:原写「例题」;这是 PyJHora 测试转录的数值夹具,不是带书名页码的书中例题,BUG-1622〕 | **流派差 V2** | | Saptavargaja:月亮、水星根本三角的起点 | 月亮金牛 4°,水星处女 16° | 与 VedAstro 相同;疑出自 Raman《A Manual of Hindu Astrology》,未能核到页码 | BPHS 3.51–54 是 3° 和 15° | **流派差 V3** | | Saptavargaja:分盘里是否算根本三角 | 只在本命盘算 | Raman §30:「only when it is in its Moolatrikona Rasi」 | saravali、jyotishganit 在各分盘也按星座算 | **流派差 V4** | | Saptavargaja:暂时友敌 | 按本命盘位置 | Raman 例 6 | saravali 说「两种意见都有」 | **流派差 V5** | @@ -96,7 +96,7 @@ | 编号 | 选项(本仓现状写在前面) | 出处 | 影响大小 | |---|---|---|---| | V1 | Saptavargaja 分值:Raman / Sripati 22.5 / 7.5 / 3.75 / 1.875,还是 BPHS 20 / 10 / 4 / 2 | Raman §30;BPHS 27.2–3 梵文「bhūtābdhayaḥ khāgninakhāstithyo daśa yugāḥ karāḥ」 | 每个分盘 ±2.5;Saptavargaja 合计最多约 ±17 | -| V2 | 本命盘根本三角:按度数范围,还是按整个星座 | BPHS 3.51–54;PyJHora、VP Jain 夹具(PyJHora 测试转录,非书中例题,BUG-1613)按整个星座 | 每次 15;19 张盘里出现 5 次 | +| V2 | 本命盘根本三角:按度数范围,还是按整个星座 | BPHS 3.51–54;PyJHora、VP Jain 夹具(PyJHora 测试转录,非书中例题,BUG-1622)按整个星座 | 每次 15;19 张盘里出现 5 次 | | V3 | 月亮、水星根本三角的起点:4° / 16°,还是 BPHS 的 3° / 15° | BPHS 3.51–54;BUG-1575 | 只影响落在这 1° 里的盘 | | V4 | 分盘里算不算根本三角 | Raman §30;saravali | 每次 15 | | V5 | 暂时友敌按本命盘,还是按分盘 | Raman 例 6;saravali | 中等 | @@ -140,7 +140,7 @@ V8–V11 和 Sthana 中的任何一项一旦改动,生时校正分数都会变 | 项目 | 状态 | 说明 | |---|---|---| | MEVG / Global Web Evidence | Used(部分) | 第一层:BPHS(梵文 + Santhanam 英译)、Raman GBB 原书扫描本。第二层:PyJHora、VedAstro、jyotishganit 源码。第三层:saravali(只作旁证) | -| Real Case Calibration | blocked | 只有计算示例(Raman 标准盘、VP Jain 夹具〔PyJHora 测试转录,非书中例题,BUG-1613〕),没有结果校准 | +| Real Case Calibration | blocked | 只有计算示例(Raman 标准盘、VP Jain 夹具〔PyJHora 测试转录,非书中例题,BUG-1622〕),没有结果校准 | | Functional Benefic/Malefic | not used | 只讨论计算口径,不解读盘 | | 三引擎交叉 | Used | PyJHora(同岁差 140 项)、jyotishganit(140 项,跑本地 vendored 代码)、VedAstro(只有乔布斯盘线上值 + 2024 源码) | | 预检 | `pre_work_check.py` exit 0 | | diff --git a/docs/research/pre_work_error_ledger.md b/docs/research/pre_work_error_ledger.md index a5bc8645..aaa6ffb6 100644 --- a/docs/research/pre_work_error_ledger.md +++ b/docs/research/pre_work_error_ledger.md @@ -7,7 +7,7 @@ Purpose: read this file before substantial project work. It exists to stop repea - `pre_work_check.py` 第一次 exit 1:新 worktree 没有 `.venv`,报「No usable project Python found」,六项全部没跑。用 scratchpad venv(Python 3.12 + swisseph)设 `JYOTISH_PRE_WORK_PYTHON` 重跑 exit 0、六项全部 ok。那个 venv 没有 pip,pytest 等开发依赖要用 `uv pip install --python /bin/python -r requirements-dev.txt` 装进去。 - ERR-110 重冻 `astrologer_166c_2026_11_05`(只改 shadbala.py 标签与共用函数):密封 20 条、报时 900 条与 `astrologer_166b_2026_11_04` 逐条相同。教训:① 隔天重冻时合同顶层 `evaluated_on` 也要改成新报告的日期,`test_contract_tracks_actual_current_scorer_and_dataset_audit` 会比;② 报时回放约 2.5 分钟,密封几秒;③ 所有冻结文件改动先放一个提交,重冻放在本分支全部代码提交之后,回放才对应最终代码。 - 捕获重生成(证据卡、名人回测、card facts):除了本单新加的标签字段,`vedastro_cross_check.official_closure_reason` 在 `foreground_optional_evidence_timeout` 与 `official_raw_response_missing` 之间来回变、`elapsed_s` 每次不同,这是环境噪声,不是代码变化。瑜伽输出没变时不提交捕获。 -- 「V.P. Jain 例题」又出现在数据核对文档里(ERR-081 复发,BUG-1613):引用外部数值时先写清来源是书页、作者教材还是软件测试夹具。 +- 「V.P. Jain 例题」又出现在数据核对文档里(ERR-081 复发,BUG-1622):引用外部数值时先写清来源是书页、作者教材还是软件测试夹具。 ## 2026-11-04 · 数据核对 1a / 1b(worktree `/workspace/wt-data`) diff --git a/frontend/tests/rectification-confirmation-gate.test.ts b/frontend/tests/rectification-confirmation-gate.test.ts index 1c22d45c..2f8613ff 100644 --- a/frontend/tests/rectification-confirmation-gate.test.ts +++ b/frontend/tests/rectification-confirmation-gate.test.ts @@ -137,7 +137,7 @@ const diagnosticReport = JSON.parse(readFileSync( // 原因(18):#166 第二批(BUG-1590~1598)改了 functional_benefics.py、jaimini.py、narayana_dasha.py、shadbala.py、varga.py,scoring-15;20 条回放与上一份逐条相同,ERR-110 另存新记录。确认门行为与阈值不变。 // 原值(19):docs/research/sealed_holdout_rerun_astrologer_166b_2026_11_04.json // 新值(19):docs/research/sealed_holdout_rerun_astrologer_166c_2026_11_05.json -// 原因(19):#166 占星师 2026-11-05 答复(BUG-1613~1617)只改了 shadbala.py 的标签与共用水星规则函数,数值不变,仍是 scoring-15;20 条回放与上一份逐条相同,ERR-110 另存新记录。确认门行为与阈值不变。 +// 原因(19):#166 占星师 2026-11-05 答复(BUG-1622~1626)只改了 shadbala.py 的标签与共用水星规则函数,数值不变,仍是 scoring-15;20 条回放与上一份逐条相同,ERR-110 另存新记录。确认门行为与阈值不变。 const currentTreeRerun = JSON.parse(readFileSync( new URL("../../docs/research/sealed_holdout_rerun_astrologer_166c_2026_11_05.json", import.meta.url), "utf8", diff --git a/references/competitive-analysis-2026-06-05.md b/references/competitive-analysis-2026-06-05.md index d6ce371e..99eb1f40 100644 --- a/references/competitive-analysis-2026-06-05.md +++ b/references/competitive-analysis-2026-06-05.md @@ -22,7 +22,7 @@ - **可借鉴**:建立 `benchmark/baselines/` 目录,固化 JSON 基线 3. **Shadbala 外部校准(我们正在做)** - - 已对齐 BV Raman 书例和 VP Jain 夹具(2026-11-05 更正:VP Jain 一项是 PyJHora 测试 `shadbala_VPJainBook_tests` 转录的数值夹具,没有书名、版本和页码,不是书例;ERR-081、BUG-1613) + - 已对齐 BV Raman 书例和 VP Jain 夹具(2026-11-05 更正:VP Jain 一项是 PyJHora 测试 `shadbala_VPJainBook_tests` 转录的数值夹具,没有书名、版本和页码,不是书例;ERR-081、BUG-1622) - `get_planet_mean_longitude()` 用于 Chesta Bala - `planet_aspect_relationship_table()` 用于 Drik Bala - **对比**:我们的 Shadbala 仍是 partial,需要外部校准 diff --git a/references/rectification_sealed_holdout.v1.json b/references/rectification_sealed_holdout.v1.json index 4b29bdce..a4d37227 100644 --- a/references/rectification_sealed_holdout.v1.json +++ b/references/rectification_sealed_holdout.v1.json @@ -201,7 +201,7 @@ "verified_minute_claim_allowed": false, "metric_gates_passed": false, "events_per_case": 3, - "boundary": "Previously exposed v3 shadow fixed-protocol rerun after the #166 astrologer reply 2026-11-05 (BUG-1613..1617): scripts/shadbala.py adds labels only (saptavargaja_moolatrikona d1_degree_band_only_provisional, drik_mercury_jupiter quarter_only_raman_pending, MERCURY_NATURE_CONVENTION renamed, 26.11-12 citation) and moves the Mercury-by-association rule into mercury_malefic_companions() shared with the strict Gajakesari yoga, values unchanged; scoring identity stays rectification-v5-matrix-scoring-15 (ERR-110). Versus the 2026-11-04 astrologer_166b_2026_11_04 report, all 20 trials and metrics are identical. Versus the 2026-09-20 historical report, changed_trial_count is 10. Not a release metric. No tuning. Prior reports and freezes preserved byte-for-byte.", + "boundary": "Previously exposed v3 shadow fixed-protocol rerun after the #166 astrologer reply 2026-11-05 (BUG-1622..1626): scripts/shadbala.py adds labels only (saptavargaja_moolatrikona d1_degree_band_only_provisional, drik_mercury_jupiter quarter_only_raman_pending, MERCURY_NATURE_CONVENTION renamed, 26.11-12 citation) and moves the Mercury-by-association rule into mercury_malefic_companions() shared with the strict Gajakesari yoga, values unchanged; scoring identity stays rectification-v5-matrix-scoring-15 (ERR-110). Versus the 2026-11-04 astrologer_166b_2026_11_04 report, all 20 trials and metrics are identical. Versus the 2026-09-20 historical report, changed_trial_count is 10. Not a release metric. No tuning. Prior reports and freezes preserved byte-for-byte.", "report_sha256": "fc3ab48bb7418e35f8f6e40b0aca8fa12c0e9004159e6a5a06b42a2c253cd3e5", "freeze_record_sha256": "cbda0f099b520c12b6d0c2c3cbd4e1b285fff5fd424cf75e15e06689f32390d6", "replay_started_at_utc": "2026-11-05T05:54:04.133903+00:00", @@ -209,7 +209,7 @@ "previous_fixed_protocol_rerun": { "report_path": "docs/research/sealed_holdout_rerun_astrologer_166b_2026_11_04.json", "freeze_record_path": "docs/research/sealed_holdout_rerun_astrologer_166b_2026_11_04.freeze.json", - "superseded_reason": "#166 astrologer reply 2026-11-05 (BUG-1613..1617): scripts/shadbala.py adds labels only (saptavargaja_moolatrikona d1_degree_band_only_provisional, drik_mercury_jupiter quarter_only_raman_pending, MERCURY_NATURE_CONVENTION renamed, 26.11-12 citation) and moves the Mercury-by-association rule into mercury_malefic_companions() shared with the strict Gajakesari yoga, values unchanged; scoring identity stays rectification-v5-matrix-scoring-15 (ERR-110) changed frozen identity files; the sealed replay output is unchanged, and ERR-110 stored a new record. Prior astrologer_166b_2026_11_04 report and freeze preserved byte-for-byte." + "superseded_reason": "#166 astrologer reply 2026-11-05 (BUG-1622..1626): scripts/shadbala.py adds labels only (saptavargaja_moolatrikona d1_degree_band_only_provisional, drik_mercury_jupiter quarter_only_raman_pending, MERCURY_NATURE_CONVENTION renamed, 26.11-12 citation) and moves the Mercury-by-association rule into mercury_malefic_companions() shared with the strict Gajakesari yoga, values unchanged; scoring identity stays rectification-v5-matrix-scoring-15 (ERR-110) changed frozen identity files; the sealed replay output is unchanged, and ERR-110 stored a new record. Prior astrologer_166b_2026_11_04 report and freeze preserved byte-for-byte." } }, "previous_fixed_protocol_rerun": { @@ -342,13 +342,13 @@ "must_not_claim_as_release_metrics": true, "replay_started_at_utc": "2026-11-05T05:54:10.220155+00:00", "replay_finished_at_utc": "2026-11-05T05:56:39.253808+00:00", - "boundary": "Previously exposed reported-offset sensitivity after the #166 astrologer reply 2026-11-05 (BUG-1613..1617): scripts/shadbala.py adds labels only (saptavargaja_moolatrikona d1_degree_band_only_provisional, drik_mercury_jupiter quarter_only_raman_pending, MERCURY_NATURE_CONVENTION renamed, 26.11-12 citation) and moves the Mercury-by-association rule into mercury_malefic_companions() shared with the strict Gajakesari yoga, values unchanged; scoring identity stays rectification-v5-matrix-scoring-15 (ERR-110). Versus the 2026-11-04 astrologer_166b_2026_11_04 report, all 900 trials and the summary are identical (top-1 hits at +-15/30/60 4/3/0 of 300; top-3 31/34/30; delivery coverage at +-15 219). Versus the 2026-09-20 historical report, changed_trial_count is 731 of 900. Not a release metric. No tuning. Prior reports and freezes preserved byte-for-byte.", + "boundary": "Previously exposed reported-offset sensitivity after the #166 astrologer reply 2026-11-05 (BUG-1622..1626): scripts/shadbala.py adds labels only (saptavargaja_moolatrikona d1_degree_band_only_provisional, drik_mercury_jupiter quarter_only_raman_pending, MERCURY_NATURE_CONVENTION renamed, 26.11-12 citation) and moves the Mercury-by-association rule into mercury_malefic_companions() shared with the strict Gajakesari yoga, values unchanged; scoring identity stays rectification-v5-matrix-scoring-15 (ERR-110). Versus the 2026-11-04 astrologer_166b_2026_11_04 report, all 900 trials and the summary are identical (top-1 hits at +-15/30/60 4/3/0 of 300; top-3 31/34/30; delivery coverage at +-15 219). Versus the 2026-09-20 historical report, changed_trial_count is 731 of 900. Not a release metric. No tuning. Prior reports and freezes preserved byte-for-byte.", "previous_reported_offset_replay": { "report_path": "docs/research/reported_offset_astrologer_166b_2026_11_04.json", "report_sha256": "8f195b6ffa258cf55372792c1f4536c77cab96f6abcf31f1e50c54dafd9185ca", "freeze_record_path": "docs/research/reported_offset_astrologer_166b_2026_11_04.freeze.json", "freeze_record_sha256": "c9bc41bb89ee5077d1c7952124bf1a9a9f15ec0cd19449cb2efe003559fc59fb", - "superseded_reason": "#166 astrologer reply 2026-11-05 (BUG-1613..1617): scripts/shadbala.py adds labels only (saptavargaja_moolatrikona d1_degree_band_only_provisional, drik_mercury_jupiter quarter_only_raman_pending, MERCURY_NATURE_CONVENTION renamed, 26.11-12 citation) and moves the Mercury-by-association rule into mercury_malefic_companions() shared with the strict Gajakesari yoga, values unchanged; scoring identity stays rectification-v5-matrix-scoring-15 (ERR-110) changed frozen identity files; the reported-offset replay output is unchanged, and ERR-110 stored a new record. Prior astrologer_166b_2026_11_04 report and freeze preserved byte-for-byte." + "superseded_reason": "#166 astrologer reply 2026-11-05 (BUG-1622..1626): scripts/shadbala.py adds labels only (saptavargaja_moolatrikona d1_degree_band_only_provisional, drik_mercury_jupiter quarter_only_raman_pending, MERCURY_NATURE_CONVENTION renamed, 26.11-12 citation) and moves the Mercury-by-association rule into mercury_malefic_companions() shared with the strict Gajakesari yoga, values unchanged; scoring identity stays rectification-v5-matrix-scoring-15 (ERR-110) changed frozen identity files; the reported-offset replay output is unchanged, and ERR-110 stored a new record. Prior astrologer_166b_2026_11_04 report and freeze preserved byte-for-byte." } }, "previous_reported_offset_replay": { diff --git a/references/yoga_rules.json b/references/yoga_rules.json index abf9cb80..3df09204 100644 --- a/references/yoga_rules.json +++ b/references/yoga_rules.json @@ -946,7 +946,7 @@ }, { "type": "custom", - "expr": "\n# #166 Q5 (BUG-1596): PVR strict definition. Jupiter in a kendra from the Moon (previous condition),\n# conjoined or aspected by a benefic, not debilitated, not combust, not in a natural enemy's sign.\n# The strong-Jupiter substitute is a separate rule (gajakesari_strong_jupiter_variant).\n# #166 2026-11-05 (BUG-1615): a natural-malefic Mercury (same sign as any natural malefic incl. the\n# waning Moon, nodes excluded: shadbala.MERCURY_NATURE_CONVENTION via mercury_malefic_companions())\n# is not a benefic supporter. Enemy sign = natural enmity (pending); the Moon is not a supporter (pending).\ntriggers = []\nmercury_with = mercury_malefic_companions()\nlinked = [b for b in ['Venus', 'Mercury'] if b in ctx.planets and (same_house(b, 'Jupiter') or aspect(b, 'Jupiter'))]\nbenefic_links = [b for b in linked if not (b == 'Mercury' and mercury_with)]\nok = bool(benefic_links) and not debil('Jupiter') and not combust('Jupiter') and not in_natural_enemy_sign('Jupiter')\nif ok:\n triggers = [('吉星关联:' + '、'.join(PLANET_ZH.get(p, p) for p in benefic_links), 'benefic association: ' + ', '.join(benefic_links))]\n if 'Mercury' in linked and mercury_with:\n triggers.append(('水星与' + '、'.join(PLANET_ZH.get(p, p) for p in mercury_with) + '同宫,按凶星计,不算吉星支持', 'Mercury is with ' + ', '.join(mercury_with) + ' (natural malefic), not counted'))\n__result__ = ok\n", + "expr": "\n# #166 Q5 (BUG-1596): PVR strict definition. Jupiter in a kendra from the Moon (previous condition),\n# conjoined or aspected by a benefic, not debilitated, not combust, not in a natural enemy's sign.\n# The strong-Jupiter substitute is a separate rule (gajakesari_strong_jupiter_variant).\n# #166 2026-11-05 (BUG-1624): a natural-malefic Mercury (same sign as any natural malefic incl. the\n# waning Moon, nodes excluded: shadbala.MERCURY_NATURE_CONVENTION via mercury_malefic_companions())\n# is not a benefic supporter. Enemy sign = natural enmity (pending); the Moon is not a supporter (pending).\ntriggers = []\nmercury_with = mercury_malefic_companions()\nlinked = [b for b in ['Venus', 'Mercury'] if b in ctx.planets and (same_house(b, 'Jupiter') or aspect(b, 'Jupiter'))]\nbenefic_links = [b for b in linked if not (b == 'Mercury' and mercury_with)]\nok = bool(benefic_links) and not debil('Jupiter') and not combust('Jupiter') and not in_natural_enemy_sign('Jupiter')\nif ok:\n triggers = [('吉星关联:' + '、'.join(PLANET_ZH.get(p, p) for p in benefic_links), 'benefic association: ' + ', '.join(benefic_links))]\n if 'Mercury' in linked and mercury_with:\n triggers.append(('水星与' + '、'.join(PLANET_ZH.get(p, p) for p in mercury_with) + '同宫,按凶星计,不算吉星支持', 'Mercury is with ' + ', '.join(mercury_with) + ' (natural malefic), not counted'))\n__result__ = ok\n", "combo_template": "严格定义:木星受吉星合相或相照,且不落陷、不燃烧、不落敌宫", "combo_template_en": "Strict definition: Jupiter conjoined or aspected by a benefic, not debilitated, combust or in an enemy sign" } @@ -965,7 +965,7 @@ "strength": "中", "strength_en": "moderate", "enabled": true, - "source_reference": "#166 Q5 (astrologer 2026-11-04): strict definition only; the strong-Jupiter variant and the bare Moon-Jupiter kendra relation are separate rules. #166 2026-11-05 (BUG-1615): PVR §11.6 (print pp. 124-125, PDF pp. 136-137): Moon kendra AND benefic conjunction-or-aspect AND Jupiter not debilitated / combust / in an enemy sign. A natural-malefic Mercury (shadbala.MERCURY_NATURE_CONVENTION) is not a supporter. Pending astrologer review: natural vs five-fold enmity for the enemy-sign test (natural kept); whether a benefic Moon may be a supporter (excluded, not approved).", + "source_reference": "#166 Q5 (astrologer 2026-11-04): strict definition only; the strong-Jupiter variant and the bare Moon-Jupiter kendra relation are separate rules. #166 2026-11-05 (BUG-1624): PVR §11.6 (print pp. 124-125, PDF pp. 136-137): Moon kendra AND benefic conjunction-or-aspect AND Jupiter not debilitated / combust / in an enemy sign. A natural-malefic Mercury (shadbala.MERCURY_NATURE_CONVENTION) is not a supporter. Pending astrologer review: natural vs five-fold enmity for the enemy-sign test (natural kept); whether a benefic Moon may be a supporter (excluded, not approved).", "bvr_chapter": "Chapter 1" }, { @@ -990,7 +990,7 @@ }, { "type": "custom", - "expr": "\n# #166 Q5: variant only when the strict definition does not hold.\n# #166 2026-11-05 (BUG-1615): the strict check below uses the same malefic-Mercury rule as the strict\n# rule, so the two stay mutually exclusive; the variant itself uses no benefic supporter.\nmercury_with = mercury_malefic_companions()\nbenefic_links = [b for b in ['Venus', 'Mercury'] if b in ctx.planets and not (b == 'Mercury' and mercury_with) and (same_house(b, 'Jupiter') or aspect(b, 'Jupiter'))]\nstrict = bool(benefic_links) and not debil('Jupiter') and not combust('Jupiter') and not in_natural_enemy_sign('Jupiter')\nstrong_jup = exalted('Jupiter') or own('Jupiter') or moola('Jupiter')\ntriggers = [(f\"木星强:{dignity('Jupiter')}\", f\"strong Jupiter: {dignity('Jupiter')}\")] if strong_jup and not strict else []\n__result__ = strong_jup and not strict and not debil('Jupiter')\n", + "expr": "\n# #166 Q5: variant only when the strict definition does not hold.\n# #166 2026-11-05 (BUG-1624): the strict check below uses the same malefic-Mercury rule as the strict\n# rule, so the two stay mutually exclusive; the variant itself uses no benefic supporter.\nmercury_with = mercury_malefic_companions()\nbenefic_links = [b for b in ['Venus', 'Mercury'] if b in ctx.planets and not (b == 'Mercury' and mercury_with) and (same_house(b, 'Jupiter') or aspect(b, 'Jupiter'))]\nstrict = bool(benefic_links) and not debil('Jupiter') and not combust('Jupiter') and not in_natural_enemy_sign('Jupiter')\nstrong_jup = exalted('Jupiter') or own('Jupiter') or moola('Jupiter')\ntriggers = [(f\"木星强:{dignity('Jupiter')}\", f\"strong Jupiter: {dignity('Jupiter')}\")] if strong_jup and not strict else []\n__result__ = strong_jup and not strict and not debil('Jupiter')\n", "combo_template": "变体:木星强(入旺 / 本宫 / 根本三角)代替吉星关联", "combo_template_en": "Variant: a strong Jupiter (exalted / own / moolatrikona) in place of benefic association" } @@ -1009,7 +1009,7 @@ "strength": "弱", "strength_en": "weak", "enabled": true, - "source_reference": "#166 Q5: a strong Jupiter (exalted / own / moolatrikona) substitutes for the benefic association; not the strict yoga. #166 2026-11-05 (BUG-1615): shown only when the strict definition (with the malefic-Mercury rule) does not hold.", + "source_reference": "#166 Q5: a strong Jupiter (exalted / own / moolatrikona) substitutes for the benefic association; not the strict yoga. #166 2026-11-05 (BUG-1624): shown only when the strict definition (with the malefic-Mercury rule) does not hold.", "bvr_chapter": "Chapter 1" }, { @@ -11578,7 +11578,7 @@ "category": "durbhaga", "logic": { "type": "custom", - "expr": "\n# #166 Q6 (BUG-1597): Raman 300 Combinations no. 198 only (no. 199 is bvr_matrunasa_199).\n# Hemmed by, associated with, or aspected by natural malefics (OR). Aspects are named Parashari graha\n# aspects (7th; Mars 4/8, Jupiter 5/9, Saturn 3/10); Rahu / Ketu count for conjunction and hemming,\n# not for aspect (implementation choice recorded in BUG-1597). No Jaimini rasi drishti.\n# #166 2026-11-05 (BUG-1616): nodes casting no aspect is a conservative engineering choice, pending\n# astrologer review (no source found granting or denying them the 7th). Malefic set used for hemming and\n# conjunction: MALEFICS = Sun, Mars, Saturn, Rahu, Ketu; aspects from Sun, Mars, Saturn only. Mercury is\n# not treated as a malefic here. Raman edition / page pending (pp. 188-190 in earlier notes is a locator only).\ntriggers = []\nif 'Moon' in ctx.planets:\n moon_h = house_of('Moon')\n prev_h = ((moon_h - 2) % 12) + 1\n next_h = (moon_h % 12) + 1\n prev_m = [p for p in MALEFICS if p in ctx.planets and house_of(p) == prev_h]\n next_m = [p for p in MALEFICS if p in ctx.planets and house_of(p) == next_h]\n if prev_m and next_m:\n triggers.append(('凶星夹制:' + '、'.join(PLANET_ZH.get(p, p) for p in prev_m + next_m), 'hemmed: ' + ', '.join(prev_m + next_m)))\n conj = [p for p in MALEFICS if p in ctx.planets and same_house('Moon', p)]\n if conj:\n triggers.append(('与月亮同宫:' + '、'.join(PLANET_ZH.get(p, p) for p in conj), 'with Moon: ' + ', '.join(conj)))\n asp = [p for p in ('Sun', 'Mars', 'Saturn') if p in ctx.planets and not same_house('Moon', p) and aspect(p, 'Moon')]\n if asp:\n triggers.append(('相照月亮:' + '、'.join(PLANET_ZH.get(p, p) for p in asp), 'aspects Moon: ' + ', '.join(asp)))\n__result__ = bool(triggers)\n", + "expr": "\n# #166 Q6 (BUG-1597): Raman 300 Combinations no. 198 only (no. 199 is bvr_matrunasa_199).\n# Hemmed by, associated with, or aspected by natural malefics (OR). Aspects are named Parashari graha\n# aspects (7th; Mars 4/8, Jupiter 5/9, Saturn 3/10); Rahu / Ketu count for conjunction and hemming,\n# not for aspect (implementation choice recorded in BUG-1597). No Jaimini rasi drishti.\n# #166 2026-11-05 (BUG-1625): nodes casting no aspect is a conservative engineering choice, pending\n# astrologer review (no source found granting or denying them the 7th). Malefic set used for hemming and\n# conjunction: MALEFICS = Sun, Mars, Saturn, Rahu, Ketu; aspects from Sun, Mars, Saturn only. Mercury is\n# not treated as a malefic here. Raman edition / page pending (pp. 188-190 in earlier notes is a locator only).\ntriggers = []\nif 'Moon' in ctx.planets:\n moon_h = house_of('Moon')\n prev_h = ((moon_h - 2) % 12) + 1\n next_h = (moon_h % 12) + 1\n prev_m = [p for p in MALEFICS if p in ctx.planets and house_of(p) == prev_h]\n next_m = [p for p in MALEFICS if p in ctx.planets and house_of(p) == next_h]\n if prev_m and next_m:\n triggers.append(('凶星夹制:' + '、'.join(PLANET_ZH.get(p, p) for p in prev_m + next_m), 'hemmed: ' + ', '.join(prev_m + next_m)))\n conj = [p for p in MALEFICS if p in ctx.planets and same_house('Moon', p)]\n if conj:\n triggers.append(('与月亮同宫:' + '、'.join(PLANET_ZH.get(p, p) for p in conj), 'with Moon: ' + ', '.join(conj)))\n asp = [p for p in ('Sun', 'Mars', 'Saturn') if p in ctx.planets and not same_house('Moon', p) and aspect(p, 'Moon')]\n if asp:\n triggers.append(('相照月亮:' + '、'.join(PLANET_ZH.get(p, p) for p in asp), 'aspects Moon: ' + ', '.join(asp)))\n__result__ = bool(triggers)\n", "combo_template": "Raman 198:月亮受凶星夹制、合相或相照", "combo_template_en": "Raman 198: Moon hemmed, conjoined or aspected by malefics" }, diff --git a/scripts/arudha_reference/pvr_dual_lord.py b/scripts/arudha_reference/pvr_dual_lord.py index 8a78fc9a..2ffff33b 100644 --- a/scripts/arudha_reference/pvr_dual_lord.py +++ b/scripts/arudha_reference/pvr_dual_lord.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """PVR Arudha dual-lord selection for Scorpio (Mars / Ketu) and Aquarius (Saturn / Rahu). -Opt-in reference only (#166 Q28, astrologer reply 2026-11-05; BUG-1617). +Opt-in reference only (#166 Q28, astrologer reply 2026-11-05; BUG-1626). Label: "PVR 双宫主比较(参考,未进默认)". The default Arudha path (`jaimini.calc_arudha_padas`, fixed lords Mars / Saturn), the chart page, the consultation card and rectification scoring do NOT use this module. Moving it diff --git a/scripts/consultation_native_layers.py b/scripts/consultation_native_layers.py index 46d13cf9..08b5d552 100644 --- a/scripts/consultation_native_layers.py +++ b/scripts/consultation_native_layers.py @@ -165,7 +165,7 @@ def build_d9_summary(engine, chart: dict, modules: dict) -> dict: if not isinstance(pdata, dict) or not d9_row.get("sign") or not pdata.get("sign"): continue # A D9 Moolatrikona is read from the in-varga degree inside the D1 band - # (engine.VARGA_MOOLATRIKONA_BASIS): 待核 with the astrologer (#166, BUG-1613). + # (engine.VARGA_MOOLATRIKONA_BASIS): 待核 with the astrologer (#166, BUG-1622). d9_level = engine._get_dignity_level(name, d9_row["sign"], d9_row.get("degree"), d9_context) # D1: the chart's own status label (what the base section shows); its # level is read back from the same label table. @@ -196,7 +196,7 @@ def build_d9_summary(engine, chart: dict, modules: dict) -> dict: "vargottama": [name for name, row in rows.items() if row["vargottama"]], "reversals": reversals, "reversal_rule": REVERSAL_RULE, - # BUG-1613: how a D9 Moolatrikona is decided; pending astrologer review. + # BUG-1622: how a D9 Moolatrikona is decided; pending astrologer review. "moolatrikona_basis": engine.VARGA_MOOLATRIKONA_BASIS, } diff --git a/scripts/jyotish_engine.py b/scripts/jyotish_engine.py index 6645c71f..17e1dc8d 100644 --- a/scripts/jyotish_engine.py +++ b/scripts/jyotish_engine.py @@ -309,7 +309,7 @@ DEBILITATION = {'Sun': 'Libra', 'Moon': 'Scorpio', 'Mars': 'Cancer', 'Mercury': # 新值: Moon 金牛 [3, 30)、Mercury 处女 [15, 20),与 shadbala._MOOLATRIKONA 一致 # 原因: BUG-1575 / BUG-1583,BPHS 3.51–54;#166 第 18 条(占星师 2026-11-04) MOOLATRIKONA = {'Sun': ('Leo', 0, 20), 'Moon': ('Taurus', 3, 30), 'Mars': ('Aries', 0, 12), 'Mercury': ('Virgo', 15, 20), 'Jupiter': ('Sagittarius', 0, 10), 'Venus': ('Libra', 0, 15), 'Saturn': ('Aquarius', 0, 20)} -# #166 2026-11-05 (BUG-1613): in a varga (the D9 expanded table, the D9 dignity in +# #166 2026-11-05 (BUG-1622): in a varga (the D9 expanded table, the D9 dignity in # _get_dignity_level, the consultation D9 summary) a planet is marked Moolatrikona when # its in-varga degree falls inside the D1 band above. Whether and how Moolatrikona # applies in the vargas (varga sign, or in-varga degree; the D30 mapping) is 待核 with @@ -14572,7 +14572,7 @@ def cmd_jaimini(args): if mode in ('all', 'arudha'): result['arudha_padas'] = calc_arudha_padas(asc_idx, planet_lons) result['graha_padas'] = calc_graha_padas(planet_lons) - # #166 Q28 (BUG-1617): PVR §15.5.1 dual-lord comparison for the houses on + # #166 Q28 (BUG-1626): PVR §15.5.1 dual-lord comparison for the houses on # Scorpio / Aquarius, next to the default fixed-lord padas. Reference only # (PVR 双宫主比较(参考,未进默认)); arudha_padas above stays the default. try: @@ -16493,7 +16493,7 @@ def cmd_full_reading(args): 'sign': d9_sign, 'house': ((d9_sign_idx - d9_asc_idx) % 12) + 1, 'degree_in_sign': d9_deg, - # D9 Moolatrikona by in-varga degree: VARGA_MOOLATRIKONA_BASIS (待核, BUG-1613). + # D9 Moolatrikona by in-varga degree: VARGA_MOOLATRIKONA_BASIS (待核, BUG-1622). 'dignity': _get_dignity_level(d9_pn, d9_sign, d9_deg, d9_context), } jaimini_result['darakaraka'] = analyze_darakaraka({ @@ -16993,7 +16993,7 @@ def cmd_full_reading(args): is_exalted = (EXALTATION.get(pn) == d9_sign) is_debilitated = (DEBILITATION.get(pn) == d9_sign) is_moola = False - # In-varga degree inside the D1 band: VARGA_MOOLATRIKONA_BASIS (待核, BUG-1613). + # In-varga degree inside the D1 band: VARGA_MOOLATRIKONA_BASIS (待核, BUG-1622). if pn in MOOLATRIKONA: mt_sign, mt_start, mt_end = MOOLATRIKONA[pn] if mt_sign == d9_sign and mt_start <= d9_deg < mt_end: diff --git a/scripts/research/reported_offset_sweep.py b/scripts/research/reported_offset_sweep.py index 5996ee65..cd432db1 100644 --- a/scripts/research/reported_offset_sweep.py +++ b/scripts/research/reported_offset_sweep.py @@ -56,7 +56,7 @@ MINUTE_STEP = 1 # 原因: #166 第二批(BUG-1590~1598)改了 functional_benefics.py、jaimini.py、narayana_dasha.py、shadbala.py、varga.py,校正身份升到 scoring-15;ERR-110 另存新记录 # 原值: docs/research/reported_offset_astrologer_166b_2026_11_04.{freeze.json,json} # 新值: docs/research/reported_offset_astrologer_166c_2026_11_05.{freeze.json,json} -# 原因: #166 占星师 2026-11-05 答复(BUG-1613~1617)只改了 shadbala.py 的标签、注释与共用的水星规则函数(数值不变),校正身份仍是 scoring-15;ERR-110 另存新记录 +# 原因: #166 占星师 2026-11-05 答复(BUG-1622~1626)只改了 shadbala.py 的标签、注释与共用的水星规则函数(数值不变),校正身份仍是 scoring-15;ERR-110 另存新记录 FREEZE = ROOT / "docs/research/reported_offset_astrologer_166c_2026_11_05.freeze.json" REPORT = ROOT / "docs/research/reported_offset_astrologer_166c_2026_11_05.json" LEGACY_REPORT = ROOT / "docs/research/reported_offset_2026_09_20.json" diff --git a/scripts/research/sealed_holdout_rerun.py b/scripts/research/sealed_holdout_rerun.py index 825be5fb..2f898067 100644 --- a/scripts/research/sealed_holdout_rerun.py +++ b/scripts/research/sealed_holdout_rerun.py @@ -53,7 +53,7 @@ DATASET = ROOT / "references/real_case_calibration/minute_rectification_holdout_ # 原因: #166 第二批(BUG-1590~1598)改了 functional_benefics.py、jaimini.py、narayana_dasha.py、shadbala.py、varga.py,校正身份升到 scoring-15;ERR-110 另存新记录 # 原值: docs/research/sealed_holdout_rerun_astrologer_166b_2026_11_04.{freeze.json,json} # 新值: docs/research/sealed_holdout_rerun_astrologer_166c_2026_11_05.{freeze.json,json} -# 原因: #166 占星师 2026-11-05 答复(BUG-1613~1617)只改了 shadbala.py 的标签、注释与共用的水星规则函数(数值不变),校正身份仍是 scoring-15;ERR-110 另存新记录 +# 原因: #166 占星师 2026-11-05 答复(BUG-1622~1626)只改了 shadbala.py 的标签、注释与共用的水星规则函数(数值不变),校正身份仍是 scoring-15;ERR-110 另存新记录 FREEZE = ROOT / "docs/research/sealed_holdout_rerun_astrologer_166c_2026_11_05.freeze.json" REPORT = ROOT / "docs/research/sealed_holdout_rerun_astrologer_166c_2026_11_05.json" LEGACY_REPORT = ROOT / "docs/research/sealed_holdout_rerun_2026_09_20.json" diff --git a/scripts/shadbala.py b/scripts/shadbala.py index 05eb96db..2f508fd3 100644 --- a/scripts/shadbala.py +++ b/scripts/shadbala.py @@ -128,7 +128,7 @@ SPECIAL_ASPECTS = { # BUG-1584, Q16: BPHS (Santhanam p. 265) Saptavargaja 45/30/20/15/10/4/2; Raman's # 22.5/15/7.5/3.75/1.875 is a separate convention. Compound relations from D1 (Q20). SAPTAVARGAJA_CONVENTION = "bphs_27_saptavargaja_20_15_10_4_2_d1_compound" -# BUG-1613 (#166 Q17 / Q19, astrologer 2026-11-05): how the 45-virupa +# BUG-1622 (#166 Q17 / Q19, astrologer 2026-11-05): how the 45-virupa # Moolatrikona slot of Saptavargaja is applied. Santhanam BPHS 27.2-4 (print # p. 265) confirms the value 45 and says the same values apply to the other six # vargas, so "45 only in D1" is NOT a rule that text states. Still 待核 (open): @@ -141,13 +141,13 @@ SAPTAVARGAJA_CONVENTION = "bphs_27_saptavargaja_20_15_10_4_2_d1_compound" SAPTAVARGAJA_MOOLATRIKONA_CONVENTION = "d1_degree_band_only_provisional" # BUG-1586, Q24: BPHS 26.9-12 piecewise special aspects replace the general # segments for Saturn, Mars and Jupiter (not Raman's add-on bonus). -# BUG-1614 (#166 Q24, astrologer 2026-11-05): 26.11-12 (Mars [180, 210) = 60; +# BUG-1623 (#166 Q24, astrologer 2026-11-05): 26.11-12 (Mars [180, 210) = 60; # Jupiter [120, 150) and [240, 270) = 60 - offset) match Santhanam BPHS vol. 1, # print p. 256. Each branch returns the final single-aspect value (no general # value on top). Left-closed / right-open segments are an engineering # convention for the endpoints, not a rule the book spells out. DRIK_SPECIAL_ASPECT_CONVENTION = "bphs_26_9_12_piecewise" -# BUG-1614 (#166 Q23, astrologer 2026-11-05): aspects CAST BY Mercury and +# BUG-1623 (#166 Q23, astrologer 2026-11-05): aspects CAST BY Mercury and # Jupiter in Drik Bala. Three readings, none adopted as BPHS: # 1. full value replaces the quarter: 1x; # 2. Santhanam's literal English of 27.19 (print p. 284): the usual +/- quarter @@ -162,11 +162,11 @@ DRIK_MERCURY_JUPITER_CONVENTION = "quarter_only_raman_pending" # natural malefic (Sun, Mars, Saturn, waning Moon); Rahu / Ketu are not counted. # 原值: "bphs_3_11_any_malefic_same_sign_no_nodes" # 新值: 下面这个名字(行为不变) -# 原因: BUG-1614(#166 第 25 条,占星师 2026-11-05):Santhanam 3.10-11(印刷页 27) +# 原因: BUG-1623(#166 第 25 条,占星师 2026-11-05):Santhanam 3.10-11(印刷页 27) # 的自然凶星包含罗睺、计都,排除交点是本仓的实现选择,不是 BPHS 规则;符合条件的亏月 # 在集合内。印刷页 28 的译者注(亏月与水星结合时两者皆吉)是另一层,没有采用。 # 同星座、无容许度是具名的离散实现。mercury_malefic_companions() 是这条规则唯一的 -# 实现,Drik 分类与严格 Gajakesari(yoga_engine)都调用它(BUG-1615)。 +# 实现,Drik 分类与严格 Gajakesari(yoga_engine)都调用它(BUG-1624)。 MERCURY_NATURE_CONVENTION = "same_sign_any_natural_malefic_waning_moon_included_nodes_excluded_implementation_choice" # BUG-1587, Q21: Kendradi Bala by whole-sign house from the Lagna sign. KENDRADI_CONVENTION = "whole_sign_from_lagna" @@ -282,10 +282,10 @@ def mercury_malefic_companions(planets: Dict) -> list[str]: """Natural malefics sharing Mercury's sign (MERCURY_NATURE_CONVENTION). Not empty = Mercury is a natural malefic by association. Rahu / Ketu are - not counted (implementation choice, BUG-1614); the waning Moon is. + not counted (implementation choice, BUG-1623); the waning Moon is. ``planets`` rows carry ``sign`` and ``degree`` (in-sign or absolute), as for calc_shadbala and the yoga engine. Shared by Drik Bala and the strict - Gajakesari supporter check (BUG-1615), so the rule lives in one place. + Gajakesari supporter check (BUG-1624), so the rule lives in one place. """ if "Mercury" not in planets: return [] @@ -367,7 +367,7 @@ def _sphuta_drishti_virupas(angle: float, aspecting_planet: str, variant: str = Sources: jyotishvidya.com ch. 26 English; 26.11-12 (Mars, Jupiter) also checked against Santhanam BPHS vol. 1 print p. 256 (astrologer 2026-11-05, - BUG-1614). Segments are [start, end): 150, 210 and 270 belong to the next + BUG-1623). Segments are [start, end): 150, 210 and 270 belong to the next branch (engineering convention for endpoints). ``round(angle, 2)`` below snaps offsets under 0.005 deg onto the endpoint. """ @@ -425,7 +425,7 @@ def calc_drik_bala_precise(pname: str, all_planets: Dict, variant: str = "bphs") Aspects cast by Mercury and Jupiter take the same quarter as every other aspect (DRIK_MERCURY_JUPITER_CONVENTION, Raman reading; BPHS 27.19 1x / - 1.25x readings are 待核, BUG-1614). + 1.25x readings are 待核, BUG-1623). """ if pname not in all_planets: return 0.0 @@ -508,7 +508,7 @@ def calc_sthana_bala_precise(pname: str, all_planets: Dict, house: int, variant: mt_sign, mt_start, mt_end = _MOOLATRIKONA[pname] if variant == "raman_gbb": mt_start = _RAMAN_MOOLATRIKONA_START.get(pname, mt_start) - # SAPTAVARGAJA_MOOLATRIKONA_CONVENTION (provisional, 待核, BUG-1613): 45 only + # SAPTAVARGAJA_MOOLATRIKONA_CONVENTION (provisional, 待核, BUG-1622): 45 only # in D1 and only inside the degree band; BPHS 27.2-4 does not state that # restriction, the other six vargas get own sign / compound relation. if division == 1 and sign_idx == mt_sign and mt_start <= degree < mt_end: @@ -877,7 +877,7 @@ def calc_shadbala(planets: Dict, asc_sign: str, birth_hour: float, 'moon_paksha': MOON_PAKSHA_CONVENTION if context else 'legacy_approximation', 'sun_ayana': SUN_AYANA_CONVENTION if context else 'legacy_approximation', 'saptavargaja': SAPTAVARGAJA_CONVENTION, - # #166 2026-11-05 (BUG-1613 / BUG-1614): provisional / pending labels, values unchanged. + # #166 2026-11-05 (BUG-1622 / BUG-1623): provisional / pending labels, values unchanged. 'saptavargaja_moolatrikona': SAPTAVARGAJA_MOOLATRIKONA_CONVENTION, 'drik_special_aspects': DRIK_SPECIAL_ASPECT_CONVENTION, 'drik_mercury_jupiter': DRIK_MERCURY_JUPITER_CONVENTION, diff --git a/scripts/yoga_engine.py b/scripts/yoga_engine.py index ac69f3b3..0600a698 100644 --- a/scripts/yoga_engine.py +++ b/scripts/yoga_engine.py @@ -749,7 +749,7 @@ def _compiled_exec_code(expr): def _shadbala_mercury_rule(): """shadbala.mercury_malefic_companions, imported on first use. - #166 (BUG-1615): the strict Gajakesari supporter check reuses the one + #166 (BUG-1624): the strict Gajakesari supporter check reuses the one implementation of the Mercury-by-association rule (BPHS 3.10-11 as labelled by shadbala.MERCURY_NATURE_CONVENTION) instead of re-deciding it. Imported lazily because shadbala pulls in swisseph; no import cycle @@ -1735,7 +1735,7 @@ class YogaEngine: return sign in SIGN_LORDS and SIGN_LORDS[sign] in NATURAL_ENEMIES.get(p, []) def mercury_malefic_companions(): - """BUG-1615: natural malefics sharing Mercury's sign; non-empty = Mercury is a natural malefic. + """BUG-1624: natural malefics sharing Mercury's sign; non-empty = Mercury is a natural malefic. Same rule and label as Drik Bala (shadbala.MERCURY_NATURE_CONVENTION): Sun, Mars, Saturn and the waning Moon count, Rahu / Ketu do not. diff --git a/tests/test_arudha_lord_selection_pvr.py b/tests/test_arudha_lord_selection_pvr.py index 52ff1466..1928931a 100644 --- a/tests/test_arudha_lord_selection_pvr.py +++ b/tests/test_arudha_lord_selection_pvr.py @@ -1,4 +1,4 @@ -"""#166 Q28 (BUG-1617): PVR §15.5.1 Arudha dual-lord selection, opt-in reference only.""" +"""#166 Q28 (BUG-1626): PVR §15.5.1 Arudha dual-lord selection, opt-in reference only.""" from __future__ import annotations diff --git a/tests/test_astrologer_rulings_166c.py b/tests/test_astrologer_rulings_166c.py index 2fa99196..71c1333b 100644 --- a/tests/test_astrologer_rulings_166c.py +++ b/tests/test_astrologer_rulings_166c.py @@ -1,8 +1,8 @@ """#166 follow-up: astrologer reply of 2026-11-05 (Gitea #166 comment 39249). Labels and boundary tests only for Shadbala (no value changes); the strict -Gajakesari malefic-Mercury rule (BUG-1615), the Matrunasa labels (BUG-1616) -and the opt-in PVR Arudha dual-lord selector (BUG-1617) have their own tests +Gajakesari malefic-Mercury rule (BUG-1624), the Matrunasa labels (BUG-1625) +and the opt-in PVR Arudha dual-lord selector (BUG-1626) have their own tests further down / in tests/test_arudha_lord_selection_pvr.py. """ @@ -26,7 +26,7 @@ def _planets(**lons: float) -> dict: return {name: {"degree": lon} for name, lon in lons.items()} -# ── BUG-1613: Saptavargaja Moolatrikona is a provisional D1-degree-band rule ── +# ── BUG-1622: Saptavargaja Moolatrikona is a provisional D1-degree-band rule ── def test_saptavargaja_moolatrikona_label_is_provisional_and_reported() -> None: assert shadbala.SAPTAVARGAJA_MOOLATRIKONA_CONVENTION == "d1_degree_band_only_provisional" @@ -51,7 +51,7 @@ def test_saptavargaja_moolatrikona_behaviour_unchanged_d1_band_only() -> None: assert all(row[f"sapta_d{d}"] != 45.0 for d in (2, 3, 7, 9, 12, 30)) -# ── BUG-1614: Drik Mercury / Jupiter quarter label; Mercury nature relabel ──── +# ── BUG-1623: Drik Mercury / Jupiter quarter label; Mercury nature relabel ──── def test_drik_mercury_jupiter_label_is_pending_and_still_a_quarter() -> None: assert shadbala.DRIK_MERCURY_JUPITER_CONVENTION == "quarter_only_raman_pending" @@ -136,7 +136,7 @@ def test_special_aspect_offsets_below_half_hundredth_snap_to_endpoint() -> None: assert shadbala._sphuta_drishti_virupas(149.994, "Jupiter") == 30.01 -# ── BUG-1615: strict Gajakesari, a natural-malefic Mercury is not a supporter ── +# ── BUG-1624: strict Gajakesari, a natural-malefic Mercury is not a supporter ── from yoga_engine import YogaEngine # noqa: E402 @@ -196,7 +196,7 @@ def test_gajakesari_venus_supports_and_the_excluded_mercury_is_named() -> None: def test_strong_jupiter_variant_uses_the_same_mercury_rule() -> None: # Moon Aries, Jupiter exalted in Cancer with a malefic Mercury (Sun in Cancer) as its only link: - # the strict yoga fails, so the variant shows (before BUG-1615 the strict yoga held instead). + # the strict yoga fails, so the variant shows (before BUG-1624 the strict yoga held instead). positions = {"Moon": ("Aries", 10), "Jupiter": ("Cancer", 5), "Sun": ("Cancer", 28), "Mercury": ("Cancer", 20), "Venus": ("Gemini", 10), "Mars": ("Capricorn", 5), "Saturn": ("Sagittarius", 5)} rows = _yogas(positions) @@ -204,7 +204,7 @@ def test_strong_jupiter_variant_uses_the_same_mercury_rule() -> None: assert "Strong-Jupiter Gajakesari Variant" in rows -# ── BUG-1616: Matrunasa 198 labels, 199 effects describe 199 ────────────────── +# ── BUG-1625: Matrunasa 198 labels, 199 effects describe 199 ────────────────── import json # noqa: E402 @@ -243,7 +243,7 @@ def test_matrunasa_199_effects_describe_the_navamsa_chain_not_198() -> None: assert hit["triggers_zh"] == ["月亮 → 水星 → 金星,落第 6 宫"] -# ── BUG-1613: D9 Moolatrikona by in-varga degree is labelled pending ───────── +# ── BUG-1622: D9 Moolatrikona by in-varga degree is labelled pending ───────── def test_varga_moolatrikona_basis_label() -> None: import jyotish_engine diff --git a/tests/test_sealed_holdout_contract_freshness.py b/tests/test_sealed_holdout_contract_freshness.py index f8cecb5d..16368028 100644 --- a/tests/test_sealed_holdout_contract_freshness.py +++ b/tests/test_sealed_holdout_contract_freshness.py @@ -99,7 +99,7 @@ IDENTITY_FORBIDDEN_PREFIXES = ( "docs/research/sealed_holdout_rerun_astrologer_166b_2026_11_04", "docs/research/reported_offset_astrologer_166b_2026_11_04", # 原值: 排除到 astrologer_166b_2026_11_04;新值: 再排除 astrologer_166c_2026_11_05(追加) - # 原因: #166 占星师 2026-11-05 答复(BUG-1613~1617)改了 shadbala.py 的标签与共用水星规则函数,数值不变,ERR-110 另存新记录 + # 原因: #166 占星师 2026-11-05 答复(BUG-1622~1626)改了 shadbala.py 的标签与共用水星规则函数,数值不变,ERR-110 另存新记录 "docs/research/sealed_holdout_rerun_astrologer_166c_2026_11_05", "docs/research/reported_offset_astrologer_166c_2026_11_05", "docs/research/history/", diff --git a/tests/test_shadbala_service_api.py b/tests/test_shadbala_service_api.py index 8c89b4bb..2f9d371c 100644 --- a/tests/test_shadbala_service_api.py +++ b/tests/test_shadbala_service_api.py @@ -108,7 +108,7 @@ def test_birth_data_request_returns_precise_shadbala(api_base) -> None: "saptavargaja": "bphs_27_saptavargaja_20_15_10_4_2_d1_compound", # 原值: 无 saptavargaja_moolatrikona、drik_mercury_jupiter;mercury_nature "bphs_3_11_any_malefic_same_sign_no_nodes" # 新值: 补两项待核标签;mercury_nature 改名写明排除交点是实现选择(数值不变) - # 原因: BUG-1613 / BUG-1614,#166 占星师 2026-11-05 答复(第 17 / 19、23、25 条) + # 原因: BUG-1622 / BUG-1623,#166 占星师 2026-11-05 答复(第 17 / 19、23、25 条) "saptavargaja_moolatrikona": "d1_degree_band_only_provisional", "drik_special_aspects": "bphs_26_9_12_piecewise", "drik_mercury_jupiter": "quarter_only_raman_pending",