Files
Jyotisha/docs/tasks/TASK-rectification-nadi-seconds-research-20261005.md
T

14 KiB
Raw Blame History

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 秒

本仓现状

  1. 主链只用到第 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 里已经有,但从来没有进过评价集。
  2. D150 只有等分实现:scripts/divisional_charts_extended.py 中的 calc_custom_varga(degree, 150) 只是把每宫等分成 150 段。古典纳迪段(Chandra Kala Nadi 体系)按动 / 固 / 变宫区分顺排还是逆排,而且每段都有名称和描述文本。这两样本仓都没有。
  3. v5 的日精度事件:一共 244 件。43/77 例有 ≥3 件,19/77 例有 ≥5 件,4/77 例一件也没有(年精度 577 件,月精度 143 件)。
  4. v5 的「真值出生时间」大多是取整过的:77 例里有 52 例的分钟数是 5 的整数倍(:00 有 14 例,:30 有 10 例)。随机分布下只该有约 20%(约 15 例)。也就是说,标准答案本身多数只精确到 5 分钟左右,秒级没有可对照的真值。分钟数不是 5 的倍数的只有 25 例。

根因(为什么至今不能对外说秒级)

  1. 没有检验过:Sookshma / Prana 小运和 D150 这两层,是「秒级」说法唯一可能的来源,但从来没在已知出生时间的人身上测过。
  2. 「问前事对上了」这种验证分辨不出真假:小运分 5 层,每层 9 颗主星,再乘上十几张分盘,几乎任何一秒都能找到一条解释过去某天的路径。用事件定出时间,再用同一批事件证明这个时间,是循环论证。必须有安慰剂对照和留出预测。
  3. 输入本身的误差已经比秒大:岁差流派、出生地坐标、「出生时刻」的定义、出生证明取整,每一项都在几十秒到几分钟之间。

决策记录(产品 2026-10-05)

  • 批准本研究单:对竞品式的「纳迪 / 小运对日子 → 秒级」做可证伪检验。只做研究,不做实现。只有通过本单的「过门标准」,才另立实现单。
  • 本单不算重开 BUG-1091:BUG-1091(打分层,closed_by_design)关的是「给已有 42 个特征重新调权重」。本单测的是从来没进过评价集的新层(Sookshma / Prana 小运、D150),目的是证伪,不是调参。执行方不得借本单去调已有特征的权重,也不得改 DOMAIN_CONFIG 的宫位映射。
  • 结果出来之前,产品对外不说「秒级」。如果本单不过门,产品要的是一份对外口径草稿(见 N6),而不是功能。
  • 纳迪段的原文描述(Chandra Kala Nadi 各段的命运文字):仓库里没有合法来源。本单不转录、不爬取、不让模型凭记忆生成这类文本。按描述文字比对经历这一路记为 blocked,D150 只做结构层检验。

硬红线

  1. 规则先登记再跑:N1–N3 用到的「事件被解释」规则族、阈值和随机种子,必须先写进 docs/research/nadi_seconds_preregistration_2026_10_05.json 并单独 commit,然后才能第一次在 v5 上跑。PROGRESS 里写明这个 commit 的 SHA。看过结果后再改的规则,只能放进「事后」列,不能用来判过门。
  2. 真值不可见:排序器与拟合器不得读取 true_minute,也不得读取出生资料里的 time 字段作为输入。只有评测函数可以读。新增测试要断言这一点,沿用 truth_hidden_from_ranker 的检查方式。
  3. 必须有安慰剂对照:每个「对上了」的指标,都要同时报告用安慰剂日期跑出的同一指标,置换检验以「整例」为单位抽样。只报真实日期、不报安慰剂的数字,一律不算数。
  4. 不得写「秒级准确率」:所有准确率都以「与记录时间相差 ≤1 分钟 / ≤2 分钟」为口径。取整组(52 例)和非取整组(25 例)分开列,不得合并后只报有利的一组。
  5. 生产代码零改动;PYTHONHASHSEED=0,所有随机数带固定种子;所有 JSON 两次复跑逐字节一致。
  6. 快速门结果与开工基线逐条一致;隐私守卫全绿;只用 v5 已有的公开名人数据,不新增人物,不访问 astro.com。
  7. 负结果完整写出。任何一格不过门,都把数字写进 PROGRESS,不得通过调阈值凑出通过。

任务分解

N0 · 研究底座与真值审计

  • 新建 scripts/research/nadi_seconds_lib.py:
    • 对任意候选时刻,返回 v5 每件事件当天的五层 Vimshottari 主星(调用 calculate_five_level_dasha 或同一条主链的递归切分)。
    • 返回 D150 段号,两种口径:等分 calc_custom_varga,以及古典纳迪段排序(动宫顺排、固宫逆排、变宫从中段起排)。古典排序的出处写在代码注释里;出处不确定的写 variant_unverified,不得冒充定论。
  • 网格:±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 层命中。
  • 对每例、每个候选秒:计算这一秒能「解释」多少件日精度事件。
  • 报三组数字:
    • 真值分钟内各秒的拟合率;
    • 窗口内随机秒的拟合率;
    • 安慰剂日期(每件事的日期按固定种子平移 ±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。