docs(tasks): nadi second-level rectification falsification research brief (BUG-1240)

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-05 00:31:23 +08:00
co-authored by Claude Opus 5.5
parent 853772bcea
commit 4c64733f91
2 changed files with 168 additions and 0 deletions
+1
View File
@@ -422,3 +422,4 @@
| `TASK-astrologer-rulings-batch6-20261004.md` | `PROGRESS-astrologer-rulings-batch6-20261004.md` | 第七轮裁定(共享仓书面回复,产品采用;问 1 选 A):Rath 版双主星按 p.43 (a)–(e)(BUG-1227 解除 blocked,推翻第五批红线 2 的 Table 17 年数底线);第 5 级宫主度数只倒算计都(p.71 脚注 42);罗计旺陷 ±1 年;同宫两主比经度;BUG 从 1228 起 | 待验收 | 分支 `codex/astrologer-rulings-batch6-20261004`(BUG-1227~1229;校正分数文件未改、未升版本) |
| `TASK-gate-log-volume-20261004.md` | `PROGRESS-gate-log-volume-20261004.md` | 门禁 validate 单步日志 4.4 万行 / 2 MB 网页打不开(run 3170):快速门只打摘要(失败给末 200 行 + 日志文件)、前端测试门禁上 dot + 失败汇总(本机仍 TAP)、拆分 validate 为 7 个 step(产品授权改 workflow,只限拆分与重定向);检查一项不少 | **已实现待验收**(BUG-1230;未推送、未部署;Gitea 各 step 页面是否打得开留待推送后由产品确认) | 分支 `codex/gate-log-volume-20261004` |
| `TASK-consult-latency-quickwins-20261005.md` | `PROGRESS-consult-latency-quickwins-20261005.md` | 普通对话耗时两项快修:咨询链校正闸不再同步白等 VedAstro 官方快照子进程(每域约 4 s,复用顶层缓存 + 负缓存,不推翻 BUG-301);补分段计时(第 0/1 步耗时、推理 token、分类耗时进日志与 usage)。推理强度/精简说明待模型 key 另单(BUG 从 1231 起) | 待领取 | 分支 `codex/consult-latency-quickwins-20261005` |
| `TASK-rectification-nadi-seconds-research-20261005.md` | `PROGRESS-rectification-nadi-seconds-research-20261005.md` | **「纳迪秒级校准」可证伪检验(离线)**:竞品宣传「问前事到天 → 秒级」。本仓主链只用三层小运,Sookshma / Prana 与 D150 从未进评价集;v5 真值 52/77 是整 5 分钟(秒级无真值可对)。N0 五层小运 + D150 底座(前三层与主链对账 0 差)、N1 拟合率 vs 安慰剂日期(核心)、N2 留一件预测、N3 六题后区间内再细分能否提头名、N4 岁差 / 坐标 / 时间扰动的噪声地板、N5 D150 结构层(原文比对 blocked)、N6 结论 + 对外口径草稿。规则先登记再跑;不改生产代码;不得重调 BUG-1091 已关的权重 | 待领取 | 分支 `codex/rectification-nadi-seconds-research-20261005`(BUG-1240) |
@@ -0,0 +1,167 @@
# 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 列。
## 开工前置命令
```bash
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。