Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
14 KiB
14 KiB
TASK · 「纳迪秒级校准」可证伪检验(研究单,2026-10-05)
基线
origin/staging@853772bc(写作时 head;开工时以最新origin/staging为准)。- 分支
codex/rectification-nadi-seconds-research-20261005,工作树.worktrees/rectification-nadi-seconds-research-20261005。 - 离线研究,不改生产代码:不动
scripts/research/sealed_holdout_rerun.py::PRODUCTION_FILES里的冻结文件,不动scripts/active_rectification_event_engine.py、scripts/dasha_calculator_enhanced.py、scripts/divisional_charts_extended.py、任何常数,也不动frontend/。研究代码只放在scripts/research/和tests/,引擎函数只能 import,不能改。 - 数据:
references/real_case_calibration/minute_rectification_holdout_v5.json(77 例 Rodden AA 公开名人,964 件事;BUG-1090)。数据集声明的口径是ayanamsa = raman、node_mode = mean,本单默认沿用;换口径只在 N4 里做。
先读
docs/research/rectification_scoring_research_2026_09_29.md:打分层三条 no_benefit,42 个特征里 36–39 个是噪声。docs/research/rectification_varga_resolution_2026_09_30.md:盘型口径;±10 六题后 D9 / D10 头段 = 真值 88% / 86%。docs/research/holdout_v5_build_2026_09_29.md:v5 基线;六题后头名 0.64 / 0.49 / 0.26,真值在区间内 76/77、76/77、75/77。docs/research/rectification_minute_resolution_closure_2026_09_14.md§1–§2
事故实证
起因
竞品 2026-10 宣传「纳迪辅助校准,符合条件时精度最高可达秒级」,验证方式是问前事、具体到天。产品问:我们为什么做不到。
Claude 2026-10-05 的判断是:秒级的盘我们能算,做不到的是验证。但这个判断有一个没测过的缺口,所以写本单把它补上。
物理量(Claude 用 swisseph 实算;样本为上海、1990-06-15,Lahiri)
| 量 | 数值 | 含义 |
|---|---|---|
| 上升点移动速度 | 0.21–0.37°/分钟 | 这个纬度和日期,每 4 秒约走 1′ |
| D150 一段持续多久 | 32–57 秒 | 纳迪段本身就是「不到一分钟」的量级 |
| D60 一段持续多久 | 81–143 秒 | |
| 出生时间差 1 秒,Vimshottari 时间轴平移 | 0.025 天(太阳大运)到 0.084 天(金星大运) | 想把一件事对准到天,出生时间就要准到约 12–40 秒 |
| 岁差 Lahiri 与 KP 相差 | 0.097°(5.8′) | ≈ 上升点 27 秒 |
| 出生地东西方向差 10 公里(北纬 31°) | — | ≈ 恒星时 25 秒 |
本仓现状
- 主链只用到第 3 层小运:
scripts/active_rectification_event_engine.py::_active_vimshottari只返回 MD / AD / PD 三层主星,_score_event也只对这三层计分。第 4 层 Sookshma、第 5 层 Prana 的算法在scripts/dasha_calculator_enhanced.py::calculate_five_level_dasha里已经有,但从来没有进过评价集。 - D150 只有等分实现:
scripts/divisional_charts_extended.py中的calc_custom_varga(degree, 150)只是把每宫等分成 150 段。古典纳迪段(Chandra Kala Nadi 体系)按动 / 固 / 变宫区分顺排还是逆排,而且每段都有名称和描述文本。这两样本仓都没有。 - v5 的日精度事件:一共 244 件。43/77 例有 ≥3 件,19/77 例有 ≥5 件,4/77 例一件也没有(年精度 577 件,月精度 143 件)。
- v5 的「真值出生时间」大多是取整过的:77 例里有 52 例的分钟数是 5 的整数倍(:00 有 14 例,:30 有 10 例)。随机分布下只该有约 20%(约 15 例)。也就是说,标准答案本身多数只精确到 5 分钟左右,秒级没有可对照的真值。分钟数不是 5 的倍数的只有 25 例。
根因(为什么至今不能对外说秒级)
- 没有检验过:Sookshma / Prana 小运和 D150 这两层,是「秒级」说法唯一可能的来源,但从来没在已知出生时间的人身上测过。
- 「问前事对上了」这种验证分辨不出真假:小运分 5 层,每层 9 颗主星,再乘上十几张分盘,几乎任何一秒都能找到一条解释过去某天的路径。用事件定出时间,再用同一批事件证明这个时间,是循环论证。必须有安慰剂对照和留出预测。
- 输入本身的误差已经比秒大:岁差流派、出生地坐标、「出生时刻」的定义、出生证明取整,每一项都在几十秒到几分钟之间。
决策记录(产品 2026-10-05)
- 批准本研究单:对竞品式的「纳迪 / 小运对日子 → 秒级」做可证伪检验。只做研究,不做实现。只有通过本单的「过门标准」,才另立实现单。
- 本单不算重开 BUG-1091:BUG-1091(打分层,closed_by_design)关的是「给已有 42 个特征重新调权重」。本单测的是从来没进过评价集的新层(Sookshma / Prana 小运、D150),目的是证伪,不是调参。执行方不得借本单去调已有特征的权重,也不得改
DOMAIN_CONFIG的宫位映射。 - 结果出来之前,产品对外不说「秒级」。如果本单不过门,产品要的是一份对外口径草稿(见 N6),而不是功能。
- 纳迪段的原文描述(Chandra Kala Nadi 各段的命运文字):仓库里没有合法来源。本单不转录、不爬取、不让模型凭记忆生成这类文本。按描述文字比对经历这一路记为
blocked,D150 只做结构层检验。
硬红线
- 规则先登记再跑:N1–N3 用到的「事件被解释」规则族、阈值和随机种子,必须先写进
docs/research/nadi_seconds_preregistration_2026_10_05.json并单独 commit,然后才能第一次在 v5 上跑。PROGRESS 里写明这个 commit 的 SHA。看过结果后再改的规则,只能放进「事后」列,不能用来判过门。 - 真值不可见:排序器与拟合器不得读取
true_minute,也不得读取出生资料里的time字段作为输入。只有评测函数可以读。新增测试要断言这一点,沿用truth_hidden_from_ranker的检查方式。 - 必须有安慰剂对照:每个「对上了」的指标,都要同时报告用安慰剂日期跑出的同一指标,置换检验以「整例」为单位抽样。只报真实日期、不报安慰剂的数字,一律不算数。
- 不得写「秒级准确率」:所有准确率都以「与记录时间相差 ≤1 分钟 / ≤2 分钟」为口径。取整组(52 例)和非取整组(25 例)分开列,不得合并后只报有利的一组。
- 生产代码零改动;
PYTHONHASHSEED=0,所有随机数带固定种子;所有 JSON 两次复跑逐字节一致。 - 快速门结果与开工基线逐条一致;隐私守卫全绿;只用 v5 已有的公开名人数据,不新增人物,不访问 astro.com。
- 负结果完整写出。任何一格不过门,都把数字写进 PROGRESS,不得通过调阈值凑出通过。
任务分解
N0 · 研究底座与真值审计
- 新建
scripts/research/nadi_seconds_lib.py:- 对任意候选时刻,返回 v5 每件事件当天的五层 Vimshottari 主星(调用
calculate_five_level_dasha或同一条主链的递归切分)。 - 返回 D150 段号,两种口径:等分
calc_custom_varga,以及古典纳迪段排序(动宫顺排、固宫逆排、变宫从中段起排)。古典排序的出处写在代码注释里;出处不确定的写variant_unverified,不得冒充定论。
- 对任意候选时刻,返回 v5 每件事件当天的五层 Vimshottari 主星(调用
- 网格:±10 分钟窗口按 5 秒一步(241 个候选),另在记录时间 ±2 分钟内按 1 秒一步。
- 对账:前三层主星必须与
_active_vimshottari逐例、逐事件 0 差,对账结果写进 JSON。 - 真值审计表:77 例的分钟数分布、取整组与非取整组名单(只列 case_id)、每例日精度事件数。
- 验收:
tests/test_nadi_seconds_research.py覆盖以下几点:- 前三层与主链对账 0 差;
- 五层边界首尾相接;
- D150 段号在段边界两侧正确翻转;
- 跨午夜正确;
- 不读
true_minute; - 两次复跑逐字节一致。
N1 · 竞品式拟合率与安慰剂(核心)
- 规则族:在预登记里固定,至少包括以下两族:
- (a) 事件当天,第 k 层小运主星 ∈ 该领域目标宫主(
DOMAIN_CONFIG+_house_lords,只 import,不改),k 分别取 4 和 5; - (b) 第 1–5 层里有 ≥m 层命中。
- (a) 事件当天,第 k 层小运主星 ∈ 该领域目标宫主(
- 对每例、每个候选秒:计算这一秒能「解释」多少件日精度事件。
- 报三组数字:
- 真值分钟内各秒的拟合率;
- 窗口内随机秒的拟合率;
- 安慰剂日期(每件事的日期按固定种子平移 ±30–180 天;另做一组把事件在案例之间互换)下的拟合率。
- 过门:真值秒的拟合率高于安慰剂,整例置换检验 p < 0.05。样本只用 ≥3 件日精度事件的 43 例。
- 验收:表格写进研究文档。另外报一个关键数:「窗口内能解释全部日精度事件的秒占多大比例」。这个比例接近 100%,就说明「问前事对上了」分辨不出真假。
N2 · 留出预测(竞品验证方式的诚实版)
- 用 ≥4 件日精度事件的案例做留一件:用其余事件拟合出最佳秒(并列的全部保留),再看被留出的那件事在这些秒上是否被解释。
- 对照两组:同窗口内随机秒;被留出事件换成安慰剂日期。
- 过门:留出事件的解释率高于随机秒,整例 bootstrap 95% 置信区间不含 0。
N3 · 能不能找回记录时间
- N3a 单独排序:只按纳迪层拟合排序,看头名与记录时间相差 ≤1 分钟 / ≤2 分钟的比例。对照均匀随机(±10 窗口下 ≤1 分钟约 3/21)和引擎先验头名(v5 ±10 为 0.18)。
- N3b 线上六题后交付区间里再细分(这是产品真正关心的问题):沿用六题回放(
scripts/research/futile_collect_stop_replay.py的口径),在线上交付区间内用纳迪层排序,看头名 ≤1 分钟的命中率能否往上提。0.64 是 v5 文档里「头名」口径的数,不一定等于「≤1 分钟」口径;先在 ≤1 分钟口径下复现线上基线,再做比较。 - 过门(两条都要满足):
- N3b 头名 ≤1 分钟命中的提升,整例 bootstrap 95% 置信区间不含 0;
- 真值仍在区间内的比例不低于 76/77。
- 取整组和非取整组分开列;±30 / ±60 的数字只报告,不参与判定。
N4 · 输入噪声地板(不论 N1–N3 结果如何都要做)
- 在记录时间上,统计每件日精度事件当天的第 4 / 第 5 层主星,以及本命 D150 段号,在下列扰动下有多少比例发生变化:
- 岁差 Raman ↔ Lahiri ↔ KP ↔ True Chitra;
- 出生时间 ±15 秒、±30 秒、±60 秒;
- 出生地坐标东西方向 ±10 公里。
- 交点 mean ↔ true 只影响罗睺 / 计都的位置,不影响 Vimshottari,单列说明即可。
- 判定(只决定对外口径,不决定是否过门):只换一个岁差流派,第 5 层主星或 D150 段号就有 >20% 的事件 / 例子跟着变,结论就是「秒级结果跨软件不可复现」。这种情况下,即使 N1–N3 全部通过,对外文案也不得出现「秒级」。
N5 · D150 结构层(低优先)
- 不使用文本,只测结构:本命 D150 段主星是否落在事件领域目标宫主里,以及 D150 上升星座的宫主星在事件当天的小运里是否激活。规则先登记,方法同 N1(要有安慰剂)。
- 按描述文字比对经历这一路写
blocked,原因写「无合法文本来源」。
N6 · 结论、对外口径与记录
docs/research/rectification_nadi_seconds_2026_10_05.md:- 一句话结论表:N1–N5 各一行,写明是否过门、关键数字、安慰剂对照;
- N4 噪声地板表;
- 结论:通过的话,写实现单要点(改哪些模块、不改哪些模块);不通过,就
closed_by_design。
- 对外口径草稿(不论结论如何都要写,对照
frontend/docs/VOICE.md):三到五句,向用户说明我们的校正能做到什么精度、靠什么数据,以及为什么不说「秒级」。不得点名竞品。 - 同步更新:
docs/research/ACTIVE_FRONTS.md索引;docs/tasks/PROGRESS-rectification-nadi-seconds-research-20261005.md;docs/BUG_HISTORY.md对应编号的状态;docs/tasks/README.md状态板这一行。
让步顺序
N0 > N1 > N4 > N2 > N3 > N5 > N6 里的图表。
- N0、N1、N4 缺一项都不能合入。
- N2 / N3 / N5 没做的,写
not_started,不得写成结论。 - 时间不够时,先砍 N5,再砍 N3 的 ±30 / ±60 列。
开工前置命令
git fetch origin --prune
git worktree add -b codex/rectification-nadi-seconds-research-20261005 .worktrees/rectification-nadi-seconds-research-20261005 origin/staging
cd .worktrees/rectification-nadi-seconds-research-20261005
export PYTHONHASHSEED=0
python3 -m pytest -q tests/test_scoring_research.py tests/test_holdout_v5_schema.py tests/test_varga_resolution_research.py tests/test_rectification_validation_integrity_gate.py tests/test_repo_privacy_markers.py # 基线
python3 scripts/research/futile_collect_stop_replay.py --help
python3 -c "import swisseph; print(swisseph.version)"
长任务每完成一个 N 就 commit 一次检查点,因为 09-29 有子代理被限额打断后成果没落盘的教训。研究分支只 commit,不推 staging;推送由验收方完成。
BUG 编号
开工时核对 docs/BUG_HISTORY.md 当前最大号(写作时是 BUG-1230)。同日 TASK-consult-latency-quickwins-20261005 已从 BUG-1231 起编号,为避免撞号,本单预留 BUG-1240:「秒级 / 纳迪校准从未经过检验:Sookshma / Prana 小运与 D150 不在评价集内,真值时间多为取整值」。如果开工时 1240 已被占用,顺延到下一个空号,并在 PROGRESS 里写明。
执行方以 investigating 登记。研究结束后:通过的改为 resolved(另立实现单);不通过的改为 closed_by_design,并附上对外口径。
关联:BUG-560、BUG-1090、BUG-1091、BUG-1105。