docs(research): shared-engine reuse audit (Narayana/Tajika/annual return) + task brief for solar-return frame fix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-10-03 19:45:39 +08:00
co-authored by Claude Opus 5.5
parent ac588172a1
commit da95d92db2
3 changed files with 360 additions and 0 deletions
@@ -0,0 +1,264 @@
# 共享引擎复用核对:Narayana / Tajika / 年盘时刻(2026-10-03)
> 只读核对,未改代码。范围是任务书 `TASK-astrologer-rulings-batch3-20261003` 涉及的五个点,加上核对中新发现的一个年盘时刻缺陷。逐项都写了证据和可复跑的方法。
## 结论先行
| # | 问题 | 根因归类 | 网站现状(staging 部署 503c1190) | 第三批分支 ecc76274 | 还要做什么 |
|---|---|---|---|---|---|
| N1 | Narayana 起运宫强弱 | 方法差异 + 原书自相矛盾 | 产品仍用旧算法(从上升起、一律顺行),已标「旧算法」 | 7 级通则已实现:Table 15、17 复现,Table 18 不复现,按红线 3 停在 T3 | 红线 3 要改口径(见 §N1),并请占星师复核 3 处 |
| N2 | Narayana 子运 | 方法差异(原书正文、原书表、原书例题三者不一) | 产品子运:旧加权算法 | 起点按问 4;方向按起点星座查 Table 13(与原书 Table 25 一致,与 p.47 正文不一致) | 方向规则请占星师定 |
| T1 | 年主比强弱用的 Panchavargiya | 网站沿用近似值;上游自身也有同一缺陷 | `native_proxy`(D1/D2/D3/D9/D12 庙旺近似) | 已改正式五分法,规则表与上游逐字节相同 | 验收即可 |
| T2 | Muntha | 上游缺陷(同一响应两种 Muntha) | 已按本命上升 + 已满年数(BUG-1212) | 不变 | 向上游报告 |
| T3 | Mudda Dasha | 网站旧方法;上游主入口也是旧方法 | 从年主起排 | 已改出生月宿 + 已满年数起排,与年主无关 | 年长取 365.25 天未经裁定,列入问题 |
| **S1** | **太阳返照时刻(新发现)** | **网站缺陷(同步漏掉上游 7cc6425d / 46ed9399)** | 返照时刻偏 3–7 分钟;243 张年盘里年盘上升变 13 张、年主变 11 张 | 未涉及 | 新任务书 `TASK-annual-return-frame-20261003` |
测试通过不代表占星预测准确。本文所有「复现」都是**原书数字对得上**,不是应验率。
## 0. 版本事实
| 项 | 值 | 核实方式 |
|---|---|---|
| 共享仓 | `https://github.com/732642856/yinduzhanxing.git`,`origin/main` = `c7117f92`(本地 `main` 落后 14,未用本地副本) | `git fetch` 后 `git archive c7117f92` 解到临时目录运行 |
| 网站仓 | Gitea `origin/staging` = `ac588172`(纯文档);最近含门禁改动的提交 `503c1190` | `deploy/is-docs-only-range.sh 503c1190… ac588172…` 退出 0 |
| 线上 staging | `/api/health` → `deployment.gitCommit` = `apiGitCommit` = `503c1190`,`skillVersion 6.9.17` | 2026-10-03 19:26 实测 |
| 网站引擎 | 网站仓自带 `scripts/`(上游的分叉,按 sync 单逐批搬),不是运行时调上游 | `scripts/tajika_year_lord.py` 等文件头写明搬运来源 SHA |
| 第三批执行分支 | `codex/astrologer-rulings-batch3-20261003` HEAD `ecc76274`(另一会话执行中,本文未改它) | 定向测试 6 个文件 229 passed |
| 预检 | 网站仓 `scripts/pre_work_check.py` → `status: pass`(远端可见、碎片扫描、外部适配器、定向测试全过) | 上游仓预检未跑:只有归档副本,没有工作树 |
| 原书 | Sanjay Rath《Narayana Dasa》PDF,sha256 `d5b576db…`,与上游账本 `references/oracle/sanjay_rath_narayana_book_ledger_2026_08_28.json` 记录的 `source_sha256` 相同 | 下载到会话临时目录比对,未入库 |
页码说明:下文用 PDF 页脚「Page N of 194」。占星师答卷里写的 p.35–36、p.48 等可能是另一套页码,内容对得上。
## N1 Narayana 起运宫强弱
**已有能力在哪:**
- 上游 `scripts/narayana_dasha.py:select_narayana_seed_sign(strength_profile=…)`。
- `rath_p36_role_conjunction_v1`:木星、水星、宫主三个角色**各记一次、不按星体去重**;同宫或 Rasi Drishti(`_rasi_aspects`)都算。
- 默认 `jaimini_lagna_seventh_strength_v1`:按星体去重,只算 Rasi Drishti,不算同宫。
- 两者都不用 Parashari 行星相位。
- 上游用到 `rath_p36…` 的只有专题入口 `scripts/padanadhamsa.py` 和 `tests/test_rath_role_strength.py`。出生盘 Narayana 主函数 `calc_narayana_mahadasha` 的 `_NARAYANA_SEED_PROFILES` 只有 `legacy_lagna_v0` 和 `jaimini_lagna_seventh_strength_v1`,选不到它。
- 上游第 3 级以后是分开的几个 profile,各管一段:`rath_empty_sign_lord_strength_v1`、`rath_classical_exaltation_strength_v1`、`rath_single_occupant_sign_dignity_v1`、`pvr_classical_lord_sign_strength_v1`。没有一个统一的 7 级选择器。
- 网站第三批 `scripts/narayana_rath.py:compare_signs`:第 1–2 级逐行搬自 `rath_p36…`,有测试与上游函数对比;第 3–7 级按占星师第五轮问 2 拼成。
**原书原文(Page 31–32):**
- 第一来源共 8 条:
1. 含 AK 的宫;
2. 星多;
3. 尊贵;
4. 双体 > 固定 > 活动;
5. 宫主是 AK;
6. 宫主度数高者强(Chara Karaka 意义);
7. 两宫同主或宫主度数相等时,看宫主是否落奇偶相反的星座;
8. 给出较长大运者强。
- 正文说 Narayana 用 (2)(3)(4)(6) 和 (7) 或 (8)。脚注 27 却说 Narayana「只用第一来源的 (2)(3)(4),加上第二来源」。**原书在第 6 条用不用上自相矛盾。**
- 优先次序(Page 33):第一来源 (2) → 第二来源 → (3) → (4)…。与占星师问 2 一致。
**用原书软件表核对(新增证据):** 原书 20 张表的表头印有「Stronger planets and signs」,即该盘 6 对宫的强弱裁决和 2 对双主星的裁决,是原书软件输出。取其中 5 张出生盘(D1):
| 表 | 盘 | 6 对宫:书 vs 7 级通则 | 双主星 |
|---|---|---|---|
| Table 22 | Chart 14(1962-03-28 06:29 IST) | 6/6 | 2/2 |
| Table 23 | Chart 15 标准盘(1963-08-07 21:15 IST) | 6/6 | 1/2(书:水瓶取土星;我们取罗睺) |
| Table 24 | Chart 16(1954-12-19 00:20 IST) | 6/6 | 2/2 |
| Table 25 | Chart 17 Wadiyar(1884-06-04 10:18 LMT) | **4/6**(双子/射手、处女/双鱼,书取双子、处女;通则第 5 级取射手、双鱼) | 1/2(书:天蝎取计都;我们取火星) |
| Table 27 | Chart 22 Indira Gandhi(1917-11-19) | 6/6(**书取摩羯强于巨蟹**) | 2/2 |
| 合计 | | **28/30** | **8/10** |
- Wadiyar 两处不符对平均交点 / 真交点、Lahiri / Raman / True Chitra 都不敏感。两处都是「水星(1.3°)主的宫 对 木星(10.0°)主的宫」,在第 5 级判出。
- 试过「去掉第 6 条(宫主度数)」的读法:27/30,并且 Indira 的巨蟹/摩羯变成平局。这个读法被否定,不提。
**Table 18 为什么复现不了:**
- 原书 Indira 手算例(Page 62)的顺序是 (2) → 第二来源 → (3) → (4) → **(7)** → 「(5) 与 (6)」。最后一句是「Saturn is the Atmakaraka and has gained the highest longitude. Hence, we can take Cancer」。
- 可是土星**落在**巨蟹、**主**摩羯。照第 5、6 条字面(看宫主),两条都指向摩羯。
- 同一位命主,原书 Table 27 的软件裁决也是摩羯。
- 所以 Table 18 是原书手算例与原书规则、原书软件表三方不一致。不是我们的代码错。
**根因:** 方法差异 + 原书自相矛盾。网站没有调用错误。
**最小修复:** 不改代码。改的是任务书红线 3 的验收口径,见 §8 待产品决定。
**未确认:**
- 第 1 级「占据星数」是否算罗睺 / 计都(第三批算了;占星师只说「数实际星体」)。
- 第 3 级同为尊贵时比最高等级还是比个数(第三批先比最高等级再比个数,是工程选择)。
- Wadiyar 两对与两处双主星的差异原因。
- 分盘(D3/D4/D9/D10/D12/D16/D20)的 14 张软件表未核。
## N2 Narayana 子运
**已有能力(上游 `calc_narayana_antardasha`):**
| profile | 起点 | 方向 | 适用边界(上游自己写的) |
|---|---|---|---|
| `rath_table13_equal_v1` | 大运星座 | Table 13 按起点星座 | 排序表;土星 / 计都在大运宫时拒绝运行 |
| `rath_table25_lord_start_v1` | 大运宫主所在星座 | Table 13 / 11 / 14 按起点星座 | 书例复现,opt-in,「不是全局默认」 |
| `parashara_equal_v1`(配 `rath_p36…`,Padanadhamsa 走这条) | 大运宫与第 7 宫较强者的宫主所在星座 | 按**大运星座**奇偶 | 无土星 / 计都例外 |
**原书原文(Page 47–48):**
- 正文(BPHS 50.30-31):比大运宫与其第 7 宫,较强者的宫主所在星座起;方向「依大运星座奇偶」。
- J.S. 2.4.31-32 的说明:「大运星座为奇,**或其宫主落奇宫**,则顺行」。
- 土星在大运宫:子运一律顺行。
- 计都在大运宫:子运反向(Table 14)。
- Table 13 的行按「起点(Arambha)星座」排。
**用原书 Table 25(Wadiyar,36 行子运)核对:**
| 做法 | 巨蟹大运 | 双子大运 | 金牛大运(土星在内) |
|---|---|---|---|
| 原书 | 天秤起顺行 | 金牛起逆行 | 巨蟹起顺行 |
| 上游 `rath_table25_lord_start_v1` | 12/12 | 12/12 | 12/12 |
| 第三批(问 4 起点 + Table 13 按起点星座) | 12/12 | **0/12**(N1 判射手更强,从木星所在巨蟹起) | 12/12 |
| 上游 `parashara_equal_v1` + `rath_p36…` | 方向反了 | 平局拒绝运行 | 方向反了(没有土星例外) |
- 原书这张表的方向跟随**起点星座**奇偶(与 J.S. 说明的「宫主所落」一致),不跟大运星座奇偶。这和原书 p.47 正文不一致。
- 第三批选了「按起点星座」,有书例支持,但占星师问 4 没有裁方向。
- 双子大运那 12 行的差异来自 N1 的强弱判定,不是子运规则本身。
**根因:** 方法差异。上游 Padanadhamsa 那条路对 Table 25 方向错、缺土星 / 计都例外,是上游缺陷,见 §9。
**未确认:** 方向按大运星座、起点星座,还是 J.S. 的「大运星座或宫主所落」三选一,需占星师定。
## T1 年主比强弱的 Panchavargiya
**已有能力:**
- 上游 `scripts/tajika.py:_calc_native_panchavargiya_bala`:Kshetra(graha_bala)30 + Uchcha 20 + Hadda 15 + Drekkana 10 + Navamsa 5 = 80,除以 4 得满分 20。
- 关系按 Tajika 宫距:3/5/9/11 友、2/6/8/12 中、1/4/7/10 敌。
- 规则表 `references/tajika_panchavargiya_rules.json`,来源注明 K. S. Charak《A Textbook of Varshaphala》与 Shanker Adawal 公开页。
- 上游只在 `calc_tajika_strength_layers`(力量报告)里调用它。
**上游年主路径:** `calc_panchadhikari_year_lord` → `_resolve_year_lord_panchavargiya_score`。
- 本机能 import PyJHora 时,进程内调 PyJHora。
- 否则退回 `native_proxy`(`_calc_panchavargiya_bala_for_planet`,D1/D2/D3/D9/D12 庙旺分)。
- **从不调用正式五分法。** 实测上游 CLI `tajika` 在本机输出 `engine: pyjhora`,直接调函数输出 `native_proxy`:同一输入,结果随环境变。
**网站:**
- staging 部署版:一律 `native_proxy`,卡片标「Panchavargiya 为本地近似计算」。
- 第三批:改用正式五分法(`engine: tajika_native_five_fold`),缺星时 blocked,不再退回近似。规则 JSON 与上游逐字节相同。
**同一年盘的分数对比(标准盘 1963,2025 年返照,满分 20):**
| 星 | 正式五分 | 近似 |
|---|---|---|
| 太阳 | 10.01 | 14.0 |
| 月亮 | 5.31 | 12.0 |
| 火星 | 11.69 | 12.0 |
| 水星 | 11.97 | 12.5 |
| 木星 | 11.12 | 14.5 |
| 金星 | 8.48 | 14.0 |
| 土星 | 7.44 | 12.5 |
这张盘的年主因此由土星(近似)变火星(正式)。
**根因:** 网站沿用近似值(第二批的工程选择)。上游年主路径有同一缺陷。
**未确认:** 正式五分法没有外部同盘逐分量对照。上游有 PyJHora 侧车对照通道,CI 没有 PyJHora。
## T2 Muntha
**两个入口:**
- `calc_muntha(birth_asc_idx, age)`:本命上升 + 年数,正确。
- `calc_panchadhikari_year_lord`:Muntha 主候选用 `(annual_asc_sign_idx + years_from_dob) % 12`,即年盘上升 + 年数。
**上游同一响应自相矛盾(最小复现):** 上游 `c7117f92`,`python3 scripts/jyotish_engine.py tajika --year 1963 --month 8 --day 7 --hour 21 --minute 15 --lat 21.4667 --lon 84.0167 --tz 5.5 --age 62 --ayanamsa lahiri`
- `muntha.muntha_sign = Taurus`(本命双鱼 + 62);
- `year_lord.muntha_sign = Pisces`(年盘摩羯 + 62)。
- 候选因此漏了正确 Muntha 主「金星」。
另有两处 Muntha 写法:`scripts/muntha.py:calc_muntha_from_sun_sign`(从太阳星座起)和 `varshaphala._calc_muntha`。网站产品路径不走这两处。
**网站:**
- `tajika_year_lord.select_annual_year_lord` 显式传 `muntha_sign_idx = 本命上升 + 已满年数`(BUG-1212,第五轮问 6 维持)。
- 年主、卡片、Tri-Pataka 用同一个值。
- 「Muntha 星座」和「它落年盘第几宫」是两回事:网站只用星座选年主,宫位只在报告解释层显示。
**根因:** 上游缺陷。网站已修。
## T3 Mudda Dasha
**已有能力(上游 `tajika.py`):**
- `calc_mudda_dasha`:年主起排,旧。
- `calc_mudda_without_dasha_balance`:p135 无余额,也从年主起。
- `calc_mudda_with_dasha_balance`:起运星 = (已满年数 + 出生月宿序号 − 2) mod 9;余额来自本命月或年盘月;在返照时刻截断。
**上游实际调用:**
- 只有 `annual_tajika_pack.py` 用新函数。
- 上游 `cmd_tajika` 和 full-reading 第 9 步仍用 `calc_mudda_dasha`(年主起)。
- full-reading 第 9 步的年主还是 `calc_year_lord`(Muntha 主即年主),与 `cmd_tajika` 的 Panchadhikari 不同。上游三条入口三种口径。
**网站第三批:** `scripts/tajika_mudda.annual_mudda_dasha` 原样包上游新函数。
- 余额取本命月;年长 `solar_year_365_25`(另有 `savana_360` 只供研究)。
- `cmd_tajika`、full-reading 第 9 步、`solar_return_full_report` 共用 `_tajika_annual_core`,口径一致。
- 有「只改年主,Mudda 不变」的测试。
**根因:** 网站旧方法,第三批已改。上游主入口未改,是上游缺陷。
**未确认:**
- 年长 365.25 天还是 360 天,占星师未裁。
- 第三批把状态写成 `partial_verified`,上游同一函数标 `parameter_sensitive`(日期未经外部同盘对照)。建议页面口径跟上游,`upstream_status` 字段已保留。
## S1 太阳返照时刻错位(新发现,网站缺陷)
**现象:** 同一张盘、同一岁差,网站算出的返照时刻比上游晚或早几分钟。
- 例:标准盘 2025 年,网站 18:24:47、上游 18:31:03,差 6 分 16 秒。
**根因:**
- 网站 `solar_return.calc_solar_return_chart` 的目标经度取自出生盘 `compute_chart_data` 的太阳经度。
- 求解器 `_find_solar_return_swe` 用 `swe` 恒星参考系逐步逼近。
- 两套参考系对出生太阳差 15.1″,折合返照时刻约 6.3 分钟。
- 网站还把返照时刻截到整分钟再起年盘(丢秒)。
- 上游 `7cc6425d`(2026-09-08,出生太阳改在求解器同一参考系重算)和 `46ed9399`(2026-09-07,保留秒)已修。
- 网站引擎同步停在 2026-09-03 的 `f2241463`,漏了这两处。与 ERR-109「同步太阳返照时只核对函数在不在」同类。
**独立复核:** 用 PyJHora `drik.next_solar_date` 算 5 个样本年(乔布斯 2012/2015/2024、齐达内 2002、小布什 2007)。
- PyJHora 与「同一参考系 + 保留秒」版本相差 0.0 分钟;
- 与网站现状相差 −7.2~+6.8 分钟。
**影响面(9 位公开名人 × 2000–2026 年 = 243 张年盘,Lahiri,第三批代码):**
| 指标 | 结果 |
|---|---|
| 返照时刻最大偏差 | 7.2 分钟 |
| 年盘上升星座改变 | 13/243(5.3%) |
| 昼夜判定改变 | 0/243(本样本没有返照时刻正好落在日出 / 日落前后几分钟的) |
| 年主改变 | 11/243(4.5%) |
例:乔布斯 2012 年盘上升金牛 → 白羊,年主金星 → 太阳;奥巴马 2024 年盘上升双鱼 → 白羊,年主月亮 → 土星。
- 受影响的是用户可见的年盘上升、年主、Mudda 起点时刻、Sahams。
- 校正打分不用年盘(`solar_return.py`、`tajika.py` 不在冻结清单),v5 不受影响。
**最小修复:** 见 `docs/tasks/TASK-annual-return-frame-20261003.md`。必须排在第三批合入之后(两边都改 `solar_return.py`)。
## 7. 本命原始数据对齐
- 三张盘(标准盘 1963、Wadiyar 1884、Indira 1917)× 平均 / 真交点,上游与网站 `compute_chart_data` 的上升与九星经度:最大差 0.0038°(真交点算法细差约 14″),月亮差 0.0001°,其余相同。星座、宫位不受影响。
- 未核:分盘、Karaka、功能吉凶、Shadbala 各分量、原始与净化 Ashtakavarga、Vimshottari 余额与日期。不在本轮五个点范围,写为未核,不写为一致。
## 8. 待产品决定
1. **第三批红线 3 改口径**(推荐):验收集改为 Table 15、Table 17 起运宫 + 原书 5 张 D1 软件表 30 对强弱(现 28/30)+ Table 25 子运 36 行。
- Table 18 记作「原书手算例与原书规则、原书 Table 27 互相矛盾」,只能显式指定起运宫复现(现已 12/12),不再要求通则自动复现。
- 若维持原红线,Rath 版永远上不了线。
2. 太阳返照修复单是否开工(推荐开,排在第三批之后)。
## 8.1 第六轮请占星师复核(草稿,按页码给原文)
1. **第 6 条用不用。** Page 32 正文说 Narayana 用 (2)(3)(4)(6) 和 (7) 或 (8),脚注 27 说只用 (2)(3)(4) 加第二来源。您第五轮把「宫主度数」放在第 5 级,我们照做。用原书 5 张软件表核对是 28/30;去掉这一级是 27/30。请确认保留。
2. **Indira 例。** Page 62 先用 (7),再用「(5) 与 (6)」,以「土星是 AK、度数最高」取巨蟹。但土星落巨蟹、主摩羯,字面上两条都指向摩羯;原书 Table 27 对同一人也判摩羯更强。请确认 Table 18 按「书内特例、需显式指定」处理,不进通则。
3. **Wadiyar 两对。** 双子/射手、处女/双鱼,原书软件表取双子、处女,通则第 5 级取射手、双鱼(水星 1.3° 对木星 10.0°)。是否有我们漏掉的规则?
4. **子运方向。** p.47 正文「依大运星座奇偶」;J.S. 2.4.31-32「大运星座为奇或其宫主落奇宫则顺行」;原书 Table 25 三段都跟起点星座奇偶。取哪一种?
5. **Mudda 年长。** 365.25 天还是 360 天?
6. **占据星数**是否计罗睺、计都?
## 9. 给上游的缺陷报告(最小复现,供转发)
1. **Muntha 两口径。** 见 T2 的复现命令。修法:`calc_panchadhikari_year_lord` 的 Muntha 用本命上升 + 年数,或由调用方传入。
2. **年主 Panchavargiya 不用正式五分法,且随环境变。** `_resolve_year_lord_panchavargiya_score` 只走 PyJHora(进程内)或 `native_proxy`;同一输入在有 / 无 PyJHora 的机器上分数不同。修法:改用 `_calc_native_panchavargiya_bala`,PyJHora 只做对照。
3. **Mudda 三条入口三种口径。** `cmd_tajika`、full-reading 第 9 步用 `calc_mudda_dasha`(年主起),`annual_tajika_pack` 用月宿起。full-reading 年主用 `calc_year_lord`,不是 Panchadhikari。
4. **Padanadhamsa 的 Rath 子运。** `parashara_equal_v1` 按大运星座奇偶定方向、无土星 / 计都例外;对 Table 25 三段大运都不符,而上游自己的 `rath_table25_lord_start_v1` 回放 36/36。
## 10. 环境与边界
- 未改网站代码、未改上游、未推代码分支。
- 原书 PDF 只在会话临时目录比对,未入库。
- PyJHora(AGPL)只做外部数字对照,没有代码进入网站仓。
- 本文复跑脚本在会话临时目录。要固化成测试的,写在修复单里。
+1
View File
@@ -416,3 +416,4 @@
| `TASK-astrologer-rulings-batch1-20261003.md` | `PROGRESS-astrologer-rulings-batch1-20261003.md` | 占星师定稿 2026-10-03 第一批(低风险批):五大人格、Kemadruma 各只留一个主检测器;Shadbala 达标在前、分档标「网站分档」;Bhava Bala 改正式三分量;罗计不设本宫、宫主链固定传统主星;8 星制 Karaka 排位按 BPHS 修正;八分法净化值进报告/卡片(过运不动);落陷取消改条件清单;Tajika 年主如实标注。乙3 Narayana、甲1、甲8/9 不在本单(BUG 从 1204 起) | 已实现待验收 | 分支 `codex/astrologer-rulings-batch1-20261003`(未推送;BUG-1204~1212;校正分数不变、未升版本) |
| `TASK-astrologer-rulings-batch2-20261003.md` | `PROGRESS-astrologer-rulings-batch2-20261003.md` | 占星师第四轮:五大人格 D9 落陷只算减弱;Tajika 年主按 Panchadhikari 选法(移植上游 c7117f92);Narayana 实现 Sanjay Rath 版并用原书三张样表验收,不接打分;旧 Narayana 如实标注;Rath 版替换校正 Narayana 的 v5 试算(只研究)。产品选方案 A(BUG 从 1213 起) | 已实现待验收(T3 起运宫未过原书样表,按红线未接、T5 未做) | 分支 `codex/astrologer-rulings-batch2-20261003`(未推送;BUG-1213~1215;校正分数不变、未升版本) |
| `TASK-astrologer-rulings-batch3-20261003.md` | `PROGRESS-astrologer-rulings-batch3-20261003.md` | 占星师第五轮:Mudda 改出生月宿起排(与年主脱钩);年主改 Tajika 正式五分力量;Rath 版 Narayana 按原书 7 级强弱、计都反转、子运起点重做并以三张样表验收,过了再并列展示与 v5 试算(研究分支);土计同宫计都优先(产品选 A);上游两个 bug 记录(BUG 从 1216 起) | 待领取 | 分支 `codex/astrologer-rulings-batch3-20261003` |
| `TASK-annual-return-frame-20261003.md` | `PROGRESS-annual-return-frame-20261003.md` | 太阳返照时刻错位:出生太阳与求解器不同参考系(差 15″≈6 分钟)+ 年盘丢秒;243 张年盘里年盘上升变 13、年主变 11;搬上游 7cc6425d/46ed9399 两处,PyJHora 对照 ≤0.5 分钟;排在第三批之后(依据 `docs/research/shared_engine_reuse_audit_2026_10_03.md`) | 待产品确认 | 分支 `codex/annual-return-frame-20261003` |
@@ -0,0 +1,95 @@
# TASK:太阳返照时刻对齐(出生太阳同参考系 + 保留秒)— 2026-10-03
## 基线与串行
- **必须在第三批(`TASK-astrologer-rulings-batch3-20261003`,分支 `codex/astrologer-rulings-batch3-20261003`)合入 staging 之后开工。** 两边都改 `scripts/solar_return.py`,第三批 T1 还改了年运下游。
- 以合入后的 `origin/staging` 为基线。分支 `codex/annual-return-frame-20261003`,工作树 `.worktrees/annual-return-frame-20261003`。
- 依据:`docs/research/shared_engine_reuse_audit_2026_10_03.md` §S1。
- 上游参照:`/workspace/yinduzhanxing` 的 `7cc6425d`(出生太阳改在求解器同一参考系重算)和 `46ed9399`(年盘保留秒)。只读,不提交、不推送上游。
## 事故实证(按符号定位)
1. **目标经度和求解器不在同一参考系。**
- `scripts/solar_return.py:calc_solar_return_chart` 里,`birth_sun_lon = sun_data.get('degree_raw', …)` 取自 `jyotish_engine.compute_chart_data` 的出生太阳。
- `_find_solar_return_swe` 用 `_get_sun_lon_jd`(`swe.calc_ut` + `sidereal_flags`)逐步逼近。
- 标准盘(1963-08-07 21:15 IST Sambalpur,Lahiri)两者相差 15.1″,2025 年返照时刻差 6 分 16 秒(网站 18:24:47,上游 18:31:03)。
2. **年盘丢秒。** 同一函数用 `sr_hour_int, sr_minute_int` 调 `compute_chart_data`,没传 `second`,年盘时刻截到整分钟。
3. **外部复核。** PyJHora `drik.next_solar_date` 在 5 个样本年与「同参考系 + 保留秒」相差 0.0 分钟,与现状相差 −7.2~+6.8 分钟。
4. **影响面。** 9 位公开名人(`tests/test_pancha_mahapurusha_main_detector.py:FIGURES`)× 2000–2026 年 = 243 张年盘:
- 年盘上升星座变 13 张(5.3%);
- 年主变 11 张(4.5%);
- 昼夜判定变 0 张。
## 根因
网站引擎从上游同步到 `f2241463`(2026-09-03)后,`solar_return.py` 只按 BUG 单补过本地化与返照地点(`41d1c740`)。上游 9 月 7–8 日的两处修正没进来。与 ERR-109「同步太阳返照只核对函数在不在」同类。
## 决策记录
- 返照的定义是「太阳回到出生时的恒星黄经」。出生和返照必须用同一参考系计算,这不是方法分歧,而是计算错误。产品授权(2026-10-03 待用户确认后生效):按上游 `7cc6425d` / `46ed9399` 的做法修。
- 只搬这两处。上游同期加的 `position_mode`、`solar_return_time_offset_seconds`、`node_longitude_offset_arcseconds`、`annual_house_system_for_sahams` 参数**不搬**(产品不用,属研究回放参数)。
- 本地化(`_localize_return_datetime`、`annual_location`)保留网站现有实现,不回退成上游的 `birth_tz`。
## 硬红线
1. 不改冻结身份里的文件(`references/rectification_sealed_holdout.v1.json` → `production_scoring_files`)。`solar_return.py`、`tajika.py` 不在清单内;v5 77 例必须与改动前逐项相同(校正不用年盘,跑一遍证明)。
2. 不改普通对话提示词,不动迁移,不升打分版本。
3. PyJHora(AGPL)只能作为外部对照:只允许把它算出的**返照 JD 数字**写进 golden,不得 import 进产品代码或测试运行路径。
4. 改到 `references/*.json` 的字符串要有 `_en` 对照;`tests/test_report_english_dictionary.py` 单独跑。
5. 禁止 `git stash`。开工前 `df -h /`,少于 15G 停下。
## 任务分解
### T1 出生太阳与求解器同参考系
- 在 `calc_solar_return_chart` 中改为 `birth_sun_lon = _get_sun_lon_jd(birth_jd_ut, ayanamsa_name=ayanamsa_name)`;拿不到时才退回出生盘的 `degree_raw`。行文照上游 `7cc6425d`。
- `solar_return` 返回值加 `target_sun_frame: "swe_sidereal_flags"`,便于日后核对。
- **验收:**
- 新测试:标准盘 2025 年返照 JD 与 PyJHora 参照值(预先算好写死在 fixture,注明来源 `pyjhora drik.next_solar_date`)相差 ≤ 0.5 分钟;
- 另取乔布斯 2012、齐达内 2002 两例同样断言。
### T2 年盘保留秒
- 调 `compute_chart_data` 时传 `second=sr_dt_ut.second`,去掉 `sr_hour_int / sr_minute_int` 的截断。照上游 `46ed9399`。
- **验收:** 新测试断言年盘 `jd` 与返照 `jd_ut` 相差 < 1 秒。
### T3 下游与 golden
- 用真实引擎重采受影响的 golden:
- `frontend/tests/fixtures/consult-evidence-card-golden.json`;
- 报告与年运包相关 golden(以 `grep -rl "solar_return\|varshesha\|mudda" tests frontend/tests` 实测为准)。
- 每个改动的断言写「原值 / 新值 / 原因」三栏。
- **验收:**
- 进度记录附 243 张年盘前后对比表:年盘上升、昼夜、年主、Mudda 首运星(第三批后 Mudda 首运星不随年盘变,应 0 变化,作为回归证据);
- 历史报告能打开(旧报告存的是生成时的结果,不重算)。
### T4 记录
- `docs/BUG_HISTORY.md` 新条目:现象、根因(两处)、修复、验证(PyJHora 对照、243 张影响表)、防复发(同参考系测试 + 同步清单加「返照求解参考系」一行),关联 ERR-109、BUG-1026~1028。
- `docs/research/pre_work_error_ledger.md` 在 ERR-109 下补一行复发说明。
- `CHANGELOG.md`(用户可感知:约 5% 的年份年盘上升和年主会变);`PROGRESS-annual-return-frame-20261003.md`;`docs/tasks/README.md` 改状态。
## 让步顺序
T1 → T2 → T4 → T3。T1 的 PyJHora 对照不过(> 0.5 分钟)时停下回报,不做 T2 以后。
## 开工前置命令
```bash
cd /workspace/Jyotisha && git status -sb | head -1
git fetch origin --prune
git log --oneline origin/staging | grep -m1 "BUG-1218" # 确认第三批已合入,否则不开工
git worktree add -b codex/annual-return-frame-20261003 .worktrees/annual-return-frame-20261003 origin/staging
df -h /
grep -oE "BUG-1[0-9]{3}" docs/BUG_HISTORY.md | sort -u | tail -1
git -C /workspace/yinduzhanxing show 7cc6425d -- scripts/solar_return.py
git -C /workspace/yinduzhanxing show 46ed9399 -- scripts/solar_return.py
python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45
```
## 验收口径
- Python 定向测试;`run_quality_gate.py --profile quick`;另跑 `tests/test_report_english_dictionary.py`。
- v5 逐项相同。
- 前端:`tsc` 0 错;lint 0 error;`npm test` 失败名单与开工基线逐条相同。
- 不 push,由 Claude 验收后推 staging。部署后 `/api/health` 的 `gitCommit` 等于含门禁改动的提交。
## BUG 编号起点
开工时核对当前最大号。第三批计划用到 BUG-1216 起若干条,本单预计从 BUG-1220 起。