# PROGRESS · BUG-1060 双重过运 D9 目标错配(2026-09-27) - 执行方式:直接执行(产品负责人授权子代理修复证据卡工作中发现的引擎 Bug),无单独任务书。 - 基线:`origin/staging` = `5671039a`;分支 `codex/bug-1060-d9-double-transit-20260927`,工作树 `.worktrees/bug-1060-d9-double-transit-20260927`;未推送。 - 开工预检:`python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45` 退出 0,六项检查全部 ok(remote_visibility verified)。 - 冻结计分清单(ERR-110):`scripts/jyotish_engine.py` 不在 `sealed_holdout_rerun.py` `PRODUCTION_FILES` 与 holdout v2/v3 `frozen_scoring.files` 里;本轮未动任何冻结文件,未动 `scripts/jyotish_api_server.py`。 ## 改了什么 | 文件 | 改动 | | --- | --- | | `scripts/jyotish_engine.py` | D9 目标构造抽成 `_double_transit_d9_targets`;`D9_{N}宫` 改用 D9 第 N 宫星座中点,`D9_{宫主}(宫主)` 改用该星 D9 星座中点;`{宫主}_D9` / `{上升主}_D9` 保留;目标名不变;D1 / CL / 跨层代码未动 | | `tests/test_double_transit_d9_targets.py` + `tests/fixtures/double_transit_d1_cl_golden.json` | 新增 7 条回归;D1/CL golden 在基线上生成 | | `scripts/run_quality_gate.py` | 新测试进 `CORE_PYTEST_TARGETS` | | `frontend/tests/fixtures/consult-evidence-card-golden.json` | 用采集脚本重生成(未手改) | | `scripts/research/capture_consult_evidence_card_golden.py` | 只改说明:采集命令加 `JYOTISH_API_CHART_CACHE_TTL_SECONDS=0`(原因见下) | D9 目标逐条决定与理由见 `docs/BUG_HISTORY.md` BUG-1060。 ## 前后对照(公开 AA 盘,研究参考日,raman,mean node) 复现盘 7 宫(D9 上升摩羯、D9 第 7 宫巨蟹): | 目标 | 修复前 | 修复后 | | --- | --- | --- | | `D9_7宫(Cancer)` | 土星「10 宫相位」(实为对 D9 上升的相位);木星无 | 木星「同宫(7宫)」;土星无 | | `D9_Moon(宫主)` | 土星「同宫(3宫)」+「合相 3.08°」(月亮 D1 度数) | 无命中 | | `Mercury_D9(Cancer)` / `Jupiter_D9(Gemini)` | 木星同宫(7宫) / 土星 3 宫相位 | 不变 | | 摘要句 | 跨层间接 Double Transit | 不变 | 48 次直接比对(3 张公开盘 + 报告 golden 虚构输入,各 12 宫):`d1`、`cl`、`summary` 48/48 不变;`d9` 47/48 变化;`double_transit` 条目 2/48 变化,都是新增跨层条目——一张公开盘 10 宫新增 `Saturn(D1)Venus(宫主) + Jupiter(D9)D9_Venus(宫主)`;虚构输入 7 宫 2 → 4 条(D9 7 宫主与 D1 7 宫主是同一颗星,两个目标落在同一 D9 星座)。 ## Golden - 数据卡 golden:`JYOTISH_API_CHART_CACHE_TTL_SECONDS=0 PYTHONHASHSEED=0 python scripts/research/capture_consult_evidence_card_golden.py`,两次运行逐字节相同。与原文件忽略键序后唯一差异:一张公开盘双重过运结论 9 → 10 条(family / annual / timing 三路)。 - 采集可复现性:基线代码连跑采集得到 3 种不同字节(值相同、字典键序与列表顺序不同)。原因是 chart 缓存按 `sort_keys` 存盘,热缓存返回排序后的顺序;原 golden 是冷热混合顺序。TTL 0 让每次都冷算,已写进脚本说明。 - `report-density-fictional-reader.json`:内含双重过运摘要(「双重触发条目=2」),没有采集脚本、测试不与现引擎比对,本轮未重生成;按现引擎会是 4。 - 新增 D1/CL golden:在基线工作树(`5671039a`)上 `PYTHONHASHSEED=0 python tests/test_double_transit_d9_targets.py --capture` 生成,修复后重生成逐字节相同。 ## 测试 | 项 | 基线 `5671039a` | 修复后 | | --- | --- | --- | | Python 门禁集(gate-pytest-args)+ `test_consultation_native_layers` + `test_report_reader_main` + `test_report_density_facts` | 971 passed / 1 skipped | 978 passed / 1 skipped(+7 新增;同一条 skip:shadbala 私有 oracle 不随公开版分发;含 growth contract、privacy markers) | | `tests/test_double_transit_d9_targets.py` | 6 failed / 1 passed(仅 D1/CL golden 通过) | 7 passed | | 前端受影响 4 个文件(evidence-card v1/v2、projection native/timing) | — | 30/30 pass | | 前端全量(Node 22.14,`tsx --test tests/*.test.ts tests/*.test.tsx`) | 4174 / pass 4122 / fail 24 / skipped 28 / cancelled 0 | 4174 / pass 4122 / fail 24 / skipped 28 / cancelled 0 | 前端 24 条失败两边按名字逐条相同(全部是需要 Docker / PostgreSQL 的数据库与部署套件),新增失败 0。本轮没有修改任何既有断言。 ## 未做 / 另记 - BUG-1061(investigating):跨层 D1+D9 配对按目标名里的数字比对,同宫号永远配不上、9 宫会误配;改法会改变报告与数据卡条目数,需产品决定。 - 部署后 chart 缓存(15 分钟 TTL,键不含代码版本)可能短暂返回旧 D9 结果。 - 环境缺口:无 Docker,数据库 / 部署套件以与基线逐条一致的失败清单代替。 ## 验收(Claude,2026-09-27) 基于 `5671039a` 独立复跑(Node 22.14,顺序执行):tsc 0;lint 0 error;`npm test` 4174 / 24 fail / 28 skip,失败名单与 v2 基线逐条一致、无消失测试名;Python 门禁集退出 0;`tests/test_double_transit_d9_targets.py` + `tests/test_consultation_native_layers.py` 通过;build 正常。代码抽查:新 helper `_double_transit_d9_targets` 四个 D9 目标的值与标签一致,D1 / 月亮上升层与交叉层未动。部署后图表缓存最多 15 分钟内可能仍返回旧 D9 结果。BUG-1061(交叉层按目标名数字配对、「D9」里的 9 导致漏配和误配)待产品决定。