docs: renumber this branch's records BUG-1613..1617 -> BUG-1622..1626

Another session shipped a different BUG-1613 (loading curtain) to staging.
Mapping in order: 1613->1622, 1614->1623, 1615->1624, 1616->1625,
1617->1626, in BUG_HISTORY headings and bodies, CHANGELOG, ledger, research
notes, code comments, rule text, test notes and the holdout contract text.
Text only. shadbala.py and the two replay scripts are in the frozen identity,
so an ERR-110 re-freeze follows in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
This commit is contained in:
2026-11-05 15:32:05 +08:00
co-authored by Claude Opus 5.5
parent 7174fda7a9
commit 093da4468d
20 changed files with 72 additions and 72 deletions
+4 -4
View File
@@ -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 版
+11 -11
View File
@@ -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。
- 复发自:无
@@ -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) |
@@ -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 | |
+1 -1
View File
@@ -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 <venv>/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`)
@@ -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",
@@ -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,需要外部校准
@@ -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": {
+5 -5
View File
@@ -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"
},
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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,
}
+4 -4
View File
@@ -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:
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+11 -11
View File
@@ -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,
+2 -2
View File
@@ -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.
+1 -1
View File
@@ -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
+8 -8
View File
@@ -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
@@ -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/",
+1 -1
View File
@@ -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",