Nadi/D150 seconds were falsified in BUG-1240; this brief only tests D60 as a discriminator: production V9 vs V9 + D60 segment boundaries on the 77-case v5 holdout, both directions (help and harm), preregistered gates G1-G5, plus a 20-case model-in-the-loop conversation comparison. Offline, no production or frozen-file changes. Reserves BUG-1497. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 7f7321b77725c8798292f184fc038fcfaf8c11ff)
8.9 KiB
8.9 KiB
TASK · D60 换格要不要进生时校正:双向对比(研究单,2026-10-28,issue #149)
基线
origin/staging@7721aa9a(写作时 head;开工时以最新origin/staging为准,在 PROGRESS 里写下实际 SHA)。- 分支
codex/rectification-d60-two-way-20261028,工作树.worktrees/rectification-d60-two-way-20261028。 - 执行方:本地 Grok(Windows + Docker),可以调用模型。验收方:Claude。
- 离线研究,不改生产代码:不动
scripts/research/sealed_holdout_rerun.py::PRODUCTION_FILES里的冻结文件,也不动scripts/varga.py、scripts/active_rectification_event_engine.py、scripts/rectification/*。D60 计分只写在scripts/research/下的新文件里,生产链路一行不改。 - 数据:
references/real_case_calibration/minute_rectification_holdout_v5.json(77 例 Rodden AA 公开名人,964 件事,244 件日精度)。口径沿用数据集声明的ayanamsa = raman、node_mode = mean,换口径只在 G5 里做。
先读
docs/research/rectification_nadi_seconds_2026_10_05.md(BUG-1240):纳迪 / D150 秒级已经证伪。N3:±10 窗口里纳迪找回记录分钟 5/77,生产 25/77;N4:只换岁差,D150 有 73/73 例换段。本单不重开 BUG-1240,只测那次没测的 D60。docs/tasks/TASK-rectification-nadi-seconds-research-20261005.md:本单照它的写法(先登记、真值不可见、安慰剂、负结果照写)。docs/research/holdout_v5_build_2026_09_29.md:v5 基线;六题回放后头名 0.64、真值在区间内 76/77。skills/jyotish-birth-time-rectification/references/technique-routing.md:现行口径「D60 只作参考,不驱动结论」。AGENTS.md§1–§4:这是「技法可靠性判断」,适用高严谨模式和 MEVG。
起因
竞品宣传「证据够密时 D60 与纳迪分盘反向校准,收束时刻可以到秒」(#142 评论 0)。纳迪那一半已经在 BUG-1240 证伪。D60 每格 0.5°,上升约 1.5–2.5 分钟走完一格,从没在已知出生时间的人身上测过它能不能帮着分开候选。产品要求先跑对比、出报告,再决定做不做(#149,jesse 2026-10-28)。
两个组
- A 组(现状):生产 V9 引擎原样,六题回放协议同 v5 基线。
- B 组(加 D60):A 组之上,多一条 D60 换格判据。窗口内上升的 D60 格每换一次,候选分成两段;用户给出日精度事件时,按预先登记的 D60 规则给两段打分,淘汰规则与 A 组的换升判据同一套。只在研究脚本里实现。
「双向」是什么
同一批例子,两个方向都要看:
- 有没有帮助:B 组是否更常找回记录分钟、区间是否更窄。
- 有没有伤害:B 组是否更常把真值排除在区间外、是否在安慰剂日期上也一样「有帮助」(说明是噪声)、换岁差后结论是否还站得住。
只报第 1 个方向、不报第 2 个方向的数字,一律不算数。
过门标准(先登记再跑)
规则、阈值、种子先写进 docs/research/d60_two_way_preregistration_2026_10_28.json,单独 commit,然后才能第一次在 v5 上跑。PROGRESS 里写明登记 commit 早于第一次计分。
| 门 | 内容 | 过门条件 |
|---|---|---|
| G1 三引擎对账 | 在 77 例的记录时间上,本仓 D60 上升格与 PyJHora、jyotishganit 逐例比对;VedAstro 能拿到就加上,拿不到写 blocked |
本仓与至少一个外部引擎一致 ≥ 95%;不一致的例子逐条列出。G1 不过,后面全部停 |
| G2 找回记录分钟 | ±10 分钟窗口、六题回放后,头名与记录分钟相差 ≤ 2 分钟的比例,B 减 A | 整例 bootstrap 5000 次,提升的下界 > 0 |
| G3 不伤真值 | 真值仍在交付区间内的例数 | B 组不少于 A 组(基线 76/77) |
| G4 安慰剂 | 把日精度事件按 BUG-1240 的 P1(±30–180 天平移)和 P2(跨例换日期)做两套安慰剂,B 组的提升重算一遍 | 真实日期的提升必须显著高于两种安慰剂(单侧置换 9999 次,p < 0.05) |
| G5 噪声地板 | 只换岁差 Raman→Lahiri / KP / True Chitra,记录时间上 D60 上升格变化的例数比例 | 任一换法超过 20%:对外文案不得出现「到秒 / 分钟级精确」,即使 G2–G4 全过 |
取整组(记录分钟是 5 的倍数,52 例)和非取整组(25 例)分开列;判门用合并样本。
模型参与的端到端对比(报告项,不判门)
在 G1 通过后做,用来看真实对话里差别有多大:
- 从 77 例里按种子
20261028抽 20 例(取整 / 非取整按比例)。 - 每例跑两次完整校正对话:A 组一次、B 组一次,顺序按种子随机,防止先后影响。
- 校正 agent 用生产同一个模型和同一份提示;「用户」由另一个模型扮演,只能看到该例 v5 里的事件清单(日期、领域、原文摘要),看不到出生时间,回答必须来自清单,清单里没有的就答「不记得」。
- 每次记录:轮数、最终区间宽度、头名与记录分钟的差、真值是否在区间内、出现了几次反证题(#148 验收要的三项一并记下)。
- 模型温度固定,种子固定;每例每组跑 1 次,有余量再跑第 2 次看稳定性。
- 只保存对话可见文本和上面的指标,不保存模型的思维链。
硬红线
- 先登记再跑:G2–G5 的规则、阈值、种子先 commit。看过结果后改的任何东西只能写进「事后」一栏,不能用来判门。
- 真值不可见:排序器、D60 打分、扮演用户的模型都不得读取
true_minute或出生资料里的time。新增测试断言这一点,沿用truth_hidden_from_ranker的检查方式。 - 必须有安慰剂:每个「有帮助」的数字都要同时报安慰剂下的同一数字。
- 不写「秒级准确率」:准确率只用「与记录时间相差 ≤1 / ≤2 分钟」口径。
- 生产代码零改动;冻结文件零改动;
PYTHONHASHSEED=0;所有 JSON 两次复跑逐字节一致(模型对话那部分除外,写明)。 - 只用 v5 已有的公开名人数据;不新增人物,不访问 astro.com。外部引擎只在本机跑,遵守各自许可证(PyJHora 是 AGPL:只在研究脚本里调用,不复制进生产代码)。
- 模型密钥只从本机环境变量读,不写进仓库、日志或报告。
- 负结果完整写出。不过门就写不过门,不调阈值凑通过。
MEVG(AGENTS.md §3)
报告里必须有这两行,做不到写 blocked:
- MEVG / Global Web Evidence:收集公开资料里「用 D60 做生时校正」的说法与依据(经典文本出处、知名占星师的方法说明、论坛案例),按 A(经典原文 / 可复现数据)B(有案例的专业说明)C(无依据的宣传)分级。竞品宣传归 C。资料之间冲突时写明怎么取舍。
- Real Case Calibration:就是上面的 v5 77 例结果。
交付物
docs/research/d60_two_way_preregistration_2026_10_28.json(先 commit)。scripts/research/d60_two_way_run.py与tests/test_d60_two_way_research.py(真值不可见、种子固定、三引擎对账函数)。docs/research/d60_two_way_results_2026_10_28.json。- 报告
docs/research/rectification_d60_two_way_2026_10_28.md:开头一张结论表(G1–G5 过 / 不过 + 关键数字 + 对照),然后是模型端到端对比表、MEVG 两行、事后一栏、建议(做 / 不做 / 只做到哪一步)。 docs/tasks/PROGRESS-rectification-d60-two-way-20261028.md:每一步的 commit 与复跑核对。- 报告摘要贴到 issue #149。
让步顺序
G1 > G2 > G3 > G5 > G4 > 端到端对比 > MEVG 的论坛案例部分。
- G1、G2、G3、G5 缺一项都不能下结论。
- 没做的写
not_started,不得写成结论。
开工前置命令
git fetch origin --prune
git worktree add -b codex/rectification-d60-two-way-20261028 .worktrees/rectification-d60-two-way-20261028 origin/staging
cd .worktrees/rectification-d60-two-way-20261028
export PYTHONHASHSEED=0
python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45
python3 -m pytest -q tests/test_nadi_seconds_research.py tests/test_holdout_v5_schema.py tests/test_varga_resolution_research.py tests/test_repo_privacy_markers.py # 基线
python3 -c "import swisseph; print(swisseph.version)"
长任务每完成一个门就 commit 一次检查点。研究分支只 commit,不推 staging;推送由验收方完成。
BUG 编号
开工时核对 docs/BUG_HISTORY.md 当前最大号(写作时是 BUG-1496)。本单预留 BUG-1497:「D60 换格是否能帮助生时校正,从未在已知出生时间的例子上检验」,执行方以 investigating 登记。通过的改为 resolved 并另立实现单;不通过的改为 closed_by_design,附对外口径。
关联:BUG-1240、BUG-560、BUG-1090、BUG-1091。