Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LutgzyJqNhPpZy1nFsJtN3
17 KiB
任务书:完整数据版补齐(二)——研究型推运附录、星座大运第三层与研究型分盘,标注研究口径(agent 循环 issue #92,2026-10-21)
基线
- 写作基线:初稿
bd3ce0e7b(10-21),定稿origin/staging=d03a8bc86(10-23)。开工时以 #91(TASK-full-data-parity-1-20261021)A、B 两段及其修复单TASK-full-data-parity-1-b-fix-20261023都合入后的origin/staging为准;#91 未合入不得开工。 两单改同一批渲染文件(scripts/pl9_full_data_export.py、scripts/report_render/、scripts/rashi_dasha_report.py)。#91 B 段已建好scripts/annual_native/子包(含tithi_pravesh.py、dasha_children.py、report_ephemeris.py)与report_render/parity_chapters.py的中英字段标签表,本单接着用,不另起一套。 - 分支:
codex/full-data-parity-2-20261021;工作树:.worktrees/full-data-parity-2-20261021。执行方 Grok(Windows + Docker),只推这个分支。 - 上游参照(只读,放仓库外):
https://github.com/732642856/yinduzhanxing.gitmain(258e08e3)的计算模块;交付版分支codex/customer-export-frozen-20261016(1d549fe9)的customer-export/registry/delivery_timing_supplement.py与delivery_evidence_appendix.py::auxiliary_dasha_markdown。不得复制该分支的个案文件(见 #91 任务书「基线」)。 - 关联:BUG-1275(真恒星口径)、BUG-1393 / 1283(Niryaana Shoola 不编子运)、
TASK-rashi-dashas-native-20261008(星座大运出处表)、TASK-report-full-data-fix-20261008红线 4(customer_timing_supplement不搬)。
1. 现状实证(Claude,Linux,bd3ce0e7b,屏蔽 PyJHora)
1.1 上游两章的体量
产品 10-21 上传的上游英文交付版(真实个人资料,只统计字符数,不入库):
| 上游章节 | 字符 | 表行 | 占全文 |
|---|---|---|---|
| Additional Native Timing Calculations(补充推运计算数据) | 2,424,694 | 36,752 | 52% |
| Auxiliary Dasha Subperiods(辅助大运次小运数据) | 713,444 | 9,402 | 15% |
1.2 「补充推运计算数据」:计算我方全部没有
上游由 scripts/customer_timing_supplement.py::build_customer_timing_supplement(main)产出,交付版的 delivery_timing_supplement.py::timing_supplement_markdown 渲染。资料包键 worksheets.timing_and_predictive_systems.customer_timing_supplement,我方资料包里没有。
| 方法族 | 上游计算模块(行数) | 我方 |
|---|---|---|
| Tithi Ashtottari 本命,顺 / 逆两口径 | tithi_ashtottari.py(296) |
无 |
| Tithi Ashtottari 年度,三年内每对 300~400 天回归 × 顺逆 × 角度 / 时间余额 | 同上 + annual_pravesha.py(540) |
无 |
| Yoga Vimshottari 本命 | yoga_annual_dasha.py(176) |
无 |
| Saptavarga 宫主关系(Sripati 输入) | aayu_sripati_periods.py(834) |
无 |
| Buddhi Gati | buddhi_gati.py(185) |
无 |
| Kaala | kaala_dasha.py(172) |
无 |
| Sudasa(另有一条「已确认起点」固定为 blocked) | sudasa.py(585) |
无 |
| Varnada JSS(两个备选起点分开) | varnada_dasha.py(349) |
无 |
| Yoga / Nakshatra Pravesha:参考年内全部回归 + 每个回归的后继分支 + 360 Tithi 年 | annual_pravesha.py、pravesha_return_year.py(417) |
无 |
| Karana 年度三种(Julene Louis 主星表 / PVR 角宫主星 / PVR 360 Tithi 年) | karana_annual_dasha.py(535)、tithi_pravesh.py(236,#91 会先搬) |
无 |
| 当前周期定位 | 以上结果查询 | 无 |
连带依赖:conditional_dashas.py(193)、nakshatra_annual_dasha.py(96)、satabdika_annual.py(90)、transit_search.py(210)、pravesha_year_basis_diagnostic.py(91)。原生部分合计约 5,000 行。依赖链里的 pyjhora_canonical_adapter.py(356)、specialized_dasha_external_replay.py(1,545)是 PyJHora 对照,不搬。「三年逐月星历」在 #91 已做。
口径问题:这些模块取经度用 FLG_MOSEPH(Moshier 星历,不是我方的 Swiss Ephemeris 星历文件),参数 longitude_profile='apparent',可选 'true_position'(FLG_TRUEPOS,几何位置);customer_timing_supplement 全部传 'apparent';Karana 一路还写死 position_mode='apparent'。三者都不是我方 BUG-1275 之后的口径(Swiss Ephemeris + 真岁差,等价 FLG_SIDEREAL)。
1.3 「辅助大运次小运数据」:我方只到第二层
| 体系 | 我方现状(scripts/rashi_dashas_native.py::calculate_rashi_dashas,虚构盘实测) |
上游 |
|---|---|---|
| Sthira | 主运 12 / 子运 144 / 次小运 0 | 次小运 1,728 |
| Drig | 12 / 144 / 0 | 同上 |
| Shoola | 12 / 144 / 0 | 同上 |
| Navamsha | 12 / 144 / 0 | 同上,带次小运规则说明 |
| Niryaana Shoola | 只出主运(pvr_niryaana_shoola_v1);三层平手时本轮不上表(这张虚构盘即如此) |
子运 + 次小运 |
星座大运在渲染时才算(rashi_dasha_report.py::render_rashi_dasha_chapter),不在资料包 worksheets 里;对话卡读的 read_full_data_domain 只拿 worksheets,所以现在不会进对话卡。
1.4 研究型分盘(10-21 产品从 #91 移入)
上游交付版「Alternative Divisional Calculation Profiles」(3,569 字符)与「Research High-Division Raw Data」(941 字符,D81 / D108 / D144 等)由 delivery_research_vargas.py::research_varga_markdown 渲染。上游函数直接跑在我方数据上能出 4,643 字符(英文),数据来自我方 varga_research_high、varga_extended、varga_full,只缺渲染。我方现有报告结构化附录里已有少量 D81 / D108 / D144 行(英文 3 处),本单统一到研究口径章节下。
1.5 体量估算与现有上限
| 项 | 数 |
|---|---|
| #91 B 段实测(0 号虚构盘,Linux,屏蔽 PyJHora) | 英文 1,263,805 字符、中文 753,562 字符;资料包 JSON 14.1 MB;先英文后中文合计约 24 s。#91 修复单还会加解释补长、后两年全套与 72 年返照表,开工时以合入后的实测为准 |
| 本单再加约 | 3.1 M 字符 / 每种语言 |
| 预计每种语言 | 英文约 4.5 M 字符以上,中文按比例;生成时长必须先按 T1 实测外推 |
| 快照(中文 + 英文 + 事实表,存一行) | 约 10~15 MB |
代码里的上限(全部按符号定位):
| 上限 | 位置 | 数值 |
|---|---|---|
| 前端等引擎出稿 | frontend/src/lib/personal-report-longform-generate.ts ENGINE_TIMEOUT_MS |
180 s(中英两份一起算) |
| 快照存储 | personal_report_sections.payload(jsonb,迁移 20260830020000_personal_report_sections.sql) |
应用层无上限;PostgreSQL 单值约 255 MB |
| 阅读页 | personal-report-markdown-view.tsx FULL_DATA_CHAPTER_PAGE_CHARS |
全文超 20 万字符按二级标题一章一页;单章没有上限,240 万字符的一章会整页渲染;打印时全部章节一起渲染 |
| 每次打开报告 | app/api/reports/[reportId]/route.ts → readLongformSnapshot |
读整行快照(中英两份 + 事实表),看中文也会把英文一起读出来 |
| 请求体 | jyotish_api_server.py MAX_REQUEST_BYTES |
2 MiB,只限请求,不限响应 |
REPORT_DOCUMENT_MAX_BYTES 1.5 MiB |
personal-report-contract.ts |
只管封面文档,不含 Markdown,不受影响 |
2. 根因
上游交付版的这两章依赖上游的原生推运模块,我方从未移植(Kalachakra 子运已在 #91 B 段以「简化模型」补到第二层);研究型分盘只差渲染;customer_timing_supplement 当时因视位置被红线挡住(TASK-report-full-data-fix-20261008 红线 4),挡住的是口径,不是这些方法本身。
3. 决策记录
| # | 决定 | 来源 |
|---|---|---|
| E1 | 补上游「补充推运计算数据」(各方法变体)与「辅助大运次小运数据」(四种星座大运第三层,Niryaana Shoola 见 E7,Kalachakra 见 E8) | 产品,issue #92;10-21 定稿 |
| E1b | D81 / D108 / D144 研究型分盘与「其他分盘口径的计算数据」从 #91 移入本单,同样标研究口径 | 产品 2026-10-21 |
| E2 | 三章(补充推运、辅助次小运、研究型分盘)开头写明「研究口径:依赖所选方法,未经外部软件核对」,英文「Research basis: method-dependent; not checked against external software.」;已知与 PyJHora 不一致的体系逐个标出 | 产品,issue #92 |
| E3 | 这些数据不进对话卡、不进校正打分 | 产品,issue #92 |
| E4 | 位置用我方引擎口径;上游 customer_timing_supplement 用的视位置设置不得照搬。本条改写 TASK-report-full-data-fix-20261008 红线 4「customer_timing_supplement 仍不搬」为:方法可以搬,口径换成我方 |
产品,issue #92 |
| E5 | 大小不设上限,只记录字符数 / 字节数 / 生成时长;碰到前端等待(ENGINE_TIMEOUT_MS 180 s)或存储 / 接口硬上限就停下回报,不得截断 |
产品 2026-10-21 |
| E6 | 阅读页没有单章上限:240 万字符的一章会整页渲染。渲染时按方法族拆成多个二级标题(不是体量上限,是为了能翻页),拆法写进 PROGRESS | Claude(执行细节) |
| E7 | Niryaana Shoola 子运与第三层:只在有书面出处时做(书名 + 页码)。照上游实现核对其出处;找不到就不上这一层,并在报告该体系标题下与 PROGRESS 写明原因,不得自编规则(BUG-1393、#84)。Claude 10-23 先查过:上游 main 的 scripts/niryaana_shoola_dasha.py 只产主运,原文写着「Its child-period rule is not independently specified」;上游交付版里那几行子运来自未公开的冻结引擎,不能当出处。所以除非 T0 找到书面规则,默认结果是不做 |
产品 10-23(issue #92 scope-final) |
| E8 | Kalachakra 补到第三层,不改现有结果:#91 B 段已出 Kalachakra 主运与子运(标「简化模型」);本单只加第三层边界,同样标「简化模型 / Simplified model」。现有主运、子运对 3 张虚构盘逐项不变;第三层与上游规则对不上就停下回报,不自行调整 | 产品 10-23(issue #92 scope-final) |
4. 硬红线
- 口径:新模块取经度一律经我方排盘函数(Swiss Ephemeris + 真岁差,与
tests/test_sidereal_nutation_frame.py同框架)。删去FLG_MOSEPH、FLG_TRUEPOS、'apparent'参数与交点偏移;回归点求根也用我方函数。新增测试:每个方法族在出生时刻用到的日、月经度与core_chart.planets.*.degree_raw差 ≤ 1e-6°;任取一个 Tithi 回归时刻,日月角距与目标 Tithi 角差 ≤ 1e-6°。 - 隔离(E3):本单产出不写进资料包
worksheets,放在单独的键(例如packet["research_timing"])或像星座大运一样在渲染时计算。测试:(a)read_full_data_domain对 3 张虚构盘的输出不含本单任何键,对话卡逐字节不变;(b) 用语法树断言scripts/rectification*、scripts/birth_time*、校正打分入口不导入本单新模块;(c) 校正打分 golden 不变。 - PyJHora:运行时不得导入
jhora。「与 PyJHora 不一致」的标注来自离线对照:脚本放scripts/research/,只在执行方本机跑,结果存成 JSON 提交,pytest 不导入 jhora(BUG-1275 的做法)。 - 增长冻结:不改
scripts/jyotish_api_server.py;scripts/*.py根目录 452 个已到ROOT_PY_BUDGET = 452,新模块进子包(例如scripts/research_timing/,或并入 #91 的scripts/annual_native/),不得调高预算;SILENT_EXCEPT_BUDGET不增加,每个方法族失败要记日志并给出具体原因,不得把导入失败包成blocked了事。 - 引擎输出变化:验收必须全量 pytest 与开工基线逐条比对;四种星座大运的主运与子运、#91 已出的 Kalachakra 主运与子运对 3 张虚构盘逐行不变。
- 不编周期:上游注明「不提供次小运」「不推造小运」的方法照样不提供;blocked 的分支(如 Sudasa 已确认起点)只写原因,不上空表。
- 不截断(E5):不设大小上限;只有中英合计生成超过 180 s 前端等待,或存储 / 接口报错(写入失败、请求或响应被拒),才停止接线、推分支、在 PROGRESS 写清实测数和卡在哪一步,等产品决定;不得删行、抽样或降精度来压体量。
- 中英文各自从源字段生成,英文汉字 0(#89 的 200 盘测试照跑);中文卫生门(#91 新加的两条)照跑。
- 不动数据库结构;不改
.gitea/;不推main;只用虚构盘与公开名人盘。
5. 任务分解
| # | 内容 | 验收标准 |
|---|---|---|
| T0 | 盘点:逐个方法族列出上游函数、输入、出处、口径参数,以及要改成我方函数的地方;Niryaana Shoola 子运出处(E7);四种星座大运次小运规则的出处(接 TASK-rashi-dashas-native-20261008 T0 的规则表) |
PROGRESS 一张表,每格有出处或 blocked |
| T1 | 先量再接:搬两个最重的方法族(Tithi Ashtottari 年度、Yoga / Nakshatra Pravesha 后继分支),先只算不渲染,对 3 张虚构盘量耗时和输出行数,按上游行数比例外推整章大小与时长;外推超过 180 s 就停(红线 7) | PROGRESS 有实测与外推;未碰硬上限才继续 |
| T2 | 其余方法族搬进子包,改口径(红线 1),每族一个测试:固定虚构盘的周期边界 golden 来自我方引擎实跑,不手造 | 各族测试通过;红线 1 两条口径测试通过 |
| T3 | 渲染「补充推运计算数据」:章首 E2 文字;按方法族分二级标题(E6);当前周期定位表;中英双语字段标签 | 3 张虚构盘中英文出现;英文汉字 0 |
| T4 | 「辅助大运次小运数据」:Sthira / Drig / Shoola / Navamsha 次小运(按 T0 出处);Niryaana Shoola 按 E7;Kalachakra 第三层按 E8;章首 E2 文字,每个体系写所用规则 | 主运、子运逐行不变(含 Kalachakra);各体系次小运条数写进 PROGRESS;Niryaana 若不做,标题下有原因句 |
| T4b | 研究型分盘(E1b):渲染「其他分盘口径的计算数据」与 D81 / D108 / D144 原始数据,中英双语,章首 E2 文字;现有结构化附录里的零散 D81 / D108 / D144 行并入该章,不重复 | 3 张虚构盘中英文出现;全文 D81 / D108 / D144 只在研究口径章节出现 |
| T5 | PyJHora 离线对照(红线 3):10 张以上虚构盘,逐体系逐层比对,不一致的在报告该体系标题下标「与 PyJHora 不一致:差在起点 / 方向 / 年数 / 子运划分」 | 对照 JSON 与汇总表进 PROGRESS;报告标注与 JSON 一致 |
| T6 | 隔离测试(红线 2 的 a、b、c) | 全部通过 |
| T7 | 量测与文档:Linux(Claude 复测)与 Windows 生成时长;中英 Markdown 字符与字节;快照 JSON 大小;打开报告接口的响应大小与耗时;阅读页章数与最大一章。BUG_HISTORY(若有缺陷)、CHANGELOG、PROGRESS、docs/testing/full-data-parity-2-20261021.md(真机:生成、翻到两章、中英切换、打印预览、导出) |
实测数齐全;未碰硬上限,或已按红线 7 停下 |
6. 验收分工
| 检查 | Grok 自跑 | Claude 验收 |
|---|---|---|
改到的与新增的 Python 测试文件,含 test_sidereal_nutation_frame、test_rashi_dashas_native、test_full_data_domain_reader、test_report_english_edition、test_python_hygiene_budget、test_api_server_growth_contract、test_runtime_jhora_import_scan |
必跑(工作树 .venv),屏蔽 PyJHora 再跑一次 |
复验 |
前端 tsc、lint、改到的测试文件 |
动了前端才跑 | 复验 |
| Python 快速门 | 不跑 | 以 Claude 为准 |
| Python 全量 pytest 与基线逐条比对 | 不跑 | 以 Claude 为准 |
前端全量 npm test、npm run build |
不跑 | 以 Claude 为准 |
| 生成时长与体量(Linux,屏蔽 PyJHora) | Windows 数照报 | 以 Claude 的 Linux 数判是否碰 180 s |
7. 让步顺序
不让步:红线 1、2、7,E2 章首说明,英文汉字 0。时间不够时依次让出:T5 的覆盖盘数(不少于 5 张)→ Karana 三种中的 PVR 360 Tithi 年 → Tithi Ashtottari 年度的「时间余额」分支。让出的写进 PROGRESS。
8. 开工前置命令
git fetch origin --prune
git log origin/staging --oneline | grep -i "full-data-parity-1" | head # 确认 #91 两段都已合入
git worktree add -b codex/full-data-parity-2-20261021 .worktrees/full-data-parity-2-20261021 origin/staging
cd .worktrees/full-data-parity-2-20261021
git -C ../yinduzhanxing-ref fetch origin main codex/customer-export-frozen-20261016
git -C ../yinduzhanxing-ref show 258e08e3:scripts/customer_timing_supplement.py | head -60
grep -n "FLG_MOSEPH\|FLG_TRUEPOS\|apparent" ../yinduzhanxing-ref/scripts/{annual_pravesha,pravesha_return_year,karana_annual_dasha,tithi_ashtottari}.py
ls scripts/*.py | wc -l # 452 = ROOT_PY_BUDGET,新文件不得放根目录
grep -oE "^## BUG-[0-9]+" docs/BUG_HISTORY.md | sort -u | sort -t- -k2 -n | tail -1
9. BUG 编号
定稿时 staging 最大号 BUG-1423,#91 修复单合入时还会占号,开工时核对最大号 + 1 起。本单以补功能为主,只有发现缺陷才占号。