From fbf04f0b5f31cd8421bc4546840b1c833aaed810 Mon Sep 17 00:00:00 2001 From: jesse-ux Date: Fri, 16 Oct 2026 09:02:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=8A=E8=A2=AB=E9=80=90=E5=AD=97=E9=94=81?= =?UTF-8?q?=E5=AE=9A=E7=9A=84=E5=B9=B4=E8=BF=90=E5=87=BD=E6=95=B0=E6=94=B9?= =?UTF-8?q?=E5=9B=9E=E5=8E=9F=E6=A0=B7=EF=BC=8C=E5=8E=86=E5=8F=B2=E6=B8=85?= =?UTF-8?q?=E5=8D=95=E4=B8=8D=E5=86=8D=E8=A6=81=E6=B1=82=E5=B7=B2=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E7=9A=84=E5=8D=A0=E4=BD=8D=E6=96=87=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 年数表字面量留在 calc_mudda_with_dasha_balance 里。调用矩阵测试改为确认这两个路径已删并由现行模块接替。pytest 三条文件 187 通过、1 跳过、0 失败。 Co-Authored-By: Grok (agent loop) --- docs/BUG_HISTORY.md | 16 +++++++ .../PROGRESS-dasha-unify-fix-20261016.md | 42 +++++++++++++++++++ docs/tasks/README.md | 2 +- scripts/tajika.py | 4 +- tests/test_dasha_api_engine_parity.py | 10 ++++- tests/test_owner_case_purge_contract.py | 21 +++++++++- 6 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 docs/tasks/PROGRESS-dasha-unify-fix-20261016.md diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 4d18c521..20fb7b42 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -36351,4 +36351,20 @@ - 复发自:无 - 修复版本:分支 `codex/dasha-unify-20261013`。 +## BUG-1358 | 年运逐字函数被改成共享年数表,历史清单仍要求已删除的占位文件 + +- 状态:resolved +- 首次发现:2026-10-16 +- 最近更新:2026-10-16 +- 影响面:`scripts/tajika.py` 的 `calc_mudda_with_dasha_balance`;历史调用矩阵对样本路径是否存在的检查。大运接口改造和 Ashtottari 出生余额修正没有改回去。 +- 用户现象:验收时 Python 全量比基线多了两条失败。年运这段用的年数没有变,但「一个字都不能改」的合同被破坏。一份历史清单还列着两个已经删掉的占位文件,检查因此变红。 +- 触发条件:运行 `tests/test_tajika_mudda.py` 的逐字合同,以及 `tests/test_owner_case_purge_contract.py` 的调用矩阵路径检查。 +- 根因:把各处 Vimshottari 年数表收成一份时,连被逐字锁定的函数里的字面量也换成了共享表。删除占位文件时按规矩没改历史矩阵,但测试仍要求矩阵里的每个路径都存在。BUG-1216 的哈希测试能发现第一处,当时的自测清单没有跑到它。BUG-1341 的防复发没有包含这份矩阵的路径检查,所以第二处要到全量对比才红。 +- 修复:该函数里的年数表和顺序表恢复成基线字面量。年数字面量计数的白名单加上 `tajika.py`,其余文件仍只能命中共享表。矩阵测试改为断言这两个路径已不存在,并由 `scripts/dasha_registry.py` 与三个条件大运模块接替。矩阵 JSON 没改,两个旧文件没有加回来。同一文件里另一处年运函数仍引用共享表。 +- 验证:见 `docs/tasks/PROGRESS-dasha-unify-fix-20261016.md`。函数文本哈希与基线合同一致。 +- 防复发:`test_ported_function_is_verbatim` 与 `test_invocation_matrix_paths_counts_hash_and_boundaries`。 +- 相关记录:BUG-1216、BUG-1341 +- 复发自:无 +- 修复版本:分支 `codex/dasha-unify-20261013`。开工时本分支最大已用编号是 BUG-1357,1358 未被占用。 + diff --git a/docs/tasks/PROGRESS-dasha-unify-fix-20261016.md b/docs/tasks/PROGRESS-dasha-unify-fix-20261016.md new file mode 100644 index 00000000..0e1af746 --- /dev/null +++ b/docs/tasks/PROGRESS-dasha-unify-fix-20261016.md @@ -0,0 +1,42 @@ +# PROGRESS · dasha-unify 修复 · 2026-10-16 + +分支 `codex/dasha-unify-20261013`。issue #69 第 1 次打回。先把 `origin/staging`(`ef9ee62a`,只有这份修复单)合并进来,没有从 staging 另起分支,也没有改写已经推送的 `5ac88e58`。 + +## 做了什么 + +年运里那个规定一个字都不能改的函数 `calc_mudda_with_dasha_balance`,已经改回基线里的年数表字面量。函数文本哈希回到 `8569dd862cf575ac8a670115206c68cd79c5b51bf53113c07bd0e21b07f0560f`。同一文件里另一个函数 `calc_mudda_dasha` 仍引用共享年数表,那一处不在逐字合同里,没有改回去。 + +`test_ported_function_is_verbatim` 只锁定这一个函数。旁边五分力量那 8 个逐字函数的哈希仍与合同一致,本单没有改到。 + +历史调用清单 JSON 没有改。两个已删除的占位文件没有加回来。测试改为:这两个路径必须不存在,并且现行模块还在。 + +`test_historical_artifacts_are_byte_preserved_not_refreshed` 只管另一份封存归档的字节,不管这份清单,所以按修复单的办法 a 改测试,没有重新生成清单。 + +大运接口改造和 Ashtottari 出生余额修正没有重做,也没有改回去。 + +## 断言变更 + +| 位置 | 原值 | 新值 | 原因 | +| --- | --- | --- | --- | +| 年数字面量白名单 | 只有 `dasha_analyzer.py`、`divisional_charts_extended.py`。其余文件的命中必须等于 `["dasha_common.py"]` | 白名单加上 `tajika.py`。命中列表的期望仍是 `["dasha_common.py"]` | `calc_mudda_with_dasha_balance` 被逐字合同锁定,函数里的年数字面量不能换成共享表 | +| 调用矩阵路径 | 清单里每个样本路径都必须是现存文件 | `scripts/extended_dashas.py` 必须不存在,由 `scripts/dasha_registry.py` 接替。`scripts/conditional_dashas.py` 必须不存在,由 `scripts/dwisaptatisama_dasha.py`、`scripts/shattrimshatsama_dasha.py`、`scripts/dwadashottari_dasha.py` 接替。其余路径仍必须存在 | BUG-1341 删除了占位文件。清单是历史归档,不能改 JSON,也不能把旧文件加回来 | + +## 自测 + +工作树 `.venv\Scripts\python.exe -m pytest tests/test_tajika_mudda.py tests/test_owner_case_purge_contract.py tests/test_dasha_api_engine_parity.py -q --tb=no -ra`。 + +| 文件 | 收集 | +| --- | --- | +| `tests/test_tajika_mudda.py` | 170 | +| `tests/test_owner_case_purge_contract.py` | 9 | +| `tests/test_dasha_api_engine_parity.py` | 9 | + +合计 188。结果:187 通过,1 跳过,0 失败,退出码 0。跳过的是 `tests/test_tajika_mudda.py` 第 180 行:本机没有上游仓库。哈希比对写在跳过之前,对不上仍会失败;独立算出的哈希与基线合同相同。上次变红的调用矩阵那一条在这 9 条里,已通过。 + +隐私标记:`.venv\Scripts\python.exe -m pytest tests/test_repo_privacy_markers.py -q`,62 通过,0 失败,退出码 0。 + +没跑前端全量 `npm test`,没跑 Python 快速门,没跑 `test:db`(没动数据库)。 + +## 偏离 + +无超出修复单的产品改动。本机缺少上游仓库,所以上游逐字比对这一步在本机记为跳过,不记为通过。 diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 004b50c0..63b4e0cb 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -494,7 +494,7 @@ | `TASK-pl9-render-split-20261013.md` | — | render_pl9_markdown 第一阶段:搬出无依赖内部函数 | 待领取(排队:api-chart-subprocess-gate) | `codex/pl9-render-split-20261013` | | `TASK-python-hygiene-20261013.md` | — | 免费层排队开关报反、静默吞异常、功能吉凶兜底合一、测试专用脚本归位(BUG-1340) | 待领取(排队:pl9-render-split) | `codex/python-hygiene-20261013` | | `TASK-dasha-unify-20261013.md` | — | /api/dasha 改走引擎同一套实现、删占位注册表、Ashtottari 出生余额(BUG-1341、1344) | 待领取(排队:python-hygiene) | `codex/dasha-unify-20261013` | -| `TASK-dasha-unify-fix-20261016.md` | — | **#69 第 1 次打回**:`5ac88e58` 主体通过;逐字移植的 `calc_mudda_with_dasha_balance` 被改;调用矩阵仍列已删文件 | 待领取 | `codex/dasha-unify-20261013` | +| `TASK-dasha-unify-fix-20261016.md` | `PROGRESS-dasha-unify-fix-20261016.md` | **#69 第 1 次打回**:`5ac88e58` 主体通过;逐字移植的 `calc_mudda_with_dasha_balance` 被改;调用矩阵仍列已删文件 | 待验收 | `codex/dasha-unify-20261013` | | `TASK-api-server-service-extract-20261013.md` | — | API 单体第一阶段:拆出不带 HTTP 的计算类,生产伪造 handler 归零 | 待领取(排队:dasha-unify) | `codex/api-server-service-extract-20261013` | | `TASK-data-layer-types-20261013.md` | `PROGRESS-data-layer-types-20261013.md` | 数据访问层改用自己的 DataClient 类型第一阶段(BUG-1351;任务书预留的 1343 已被更大编号越过) | 待验收 | `codex/data-layer-types-20261013` | | `TASK-contracts-helpers-dedupe-20261013.md` | — | 前后端契约与小工具去重第一阶段 | 待领取(排队:frontend-dead-code、consult-route-split) | `codex/contracts-helpers-dedupe-20261013` | diff --git a/scripts/tajika.py b/scripts/tajika.py index 10cbe3e0..73a5dc5c 100644 --- a/scripts/tajika.py +++ b/scripts/tajika.py @@ -402,8 +402,8 @@ def calc_mudda_with_dasha_balance( producers rather than treating a different balance source as a label. """ - dasha_order = list(_VIMSHOTTARI_ORDER) - dasha_years = _VIMSHOTTARI_YEARS + dasha_order = ["Ketu", "Venus", "Sun", "Moon", "Mars", "Rahu", "Jupiter", "Saturn", "Mercury"] + dasha_years = {"Ketu": 7, "Venus": 20, "Sun": 6, "Moon": 10, "Mars": 7, "Rahu": 18, "Jupiter": 16, "Saturn": 19, "Mercury": 17} valid_profiles = {"moon_at_birth_time", "moon_in_varshaphala"} if not isinstance(annual_start, datetime): return {"status": "blocked", "reason": "true_solar_return_datetime_required_for_mudda_balance", "balance_profile": balance_profile} diff --git a/tests/test_dasha_api_engine_parity.py b/tests/test_dasha_api_engine_parity.py index 7bda9ff4..991c9c75 100644 --- a/tests/test_dasha_api_engine_parity.py +++ b/tests/test_dasha_api_engine_parity.py @@ -67,7 +67,15 @@ BALANCE_ANCHORS = ( ("shodashottari_dasha", "PUSHYA_INDEX"), ) -FROZEN_YEAR_TABLES = {"dasha_analyzer.py", "divisional_charts_extended.py"} +# 原值:白名单只有 dasha_analyzer.py、divisional_charts_extended.py +# 新值:加上 tajika.py +# 原因:calc_mudda_with_dasha_balance 被 test_ported_function_is_verbatim 逐字锁定, +# 函数里的年数字面量不能改成共享表引用。其余非白名单文件仍只能命中 dasha_common.py。 +FROZEN_YEAR_TABLES = { + "dasha_analyzer.py", + "divisional_charts_extended.py", + "tajika.py", +} YEAR_TABLE = re.compile( r"""['"]Ketu['"]\s*:\s*7\b.*?['"]Venus['"]\s*:\s*20\b.*?['"]Mercury['"]\s*:\s*17\b""", re.DOTALL, diff --git a/tests/test_owner_case_purge_contract.py b/tests/test_owner_case_purge_contract.py index a8887572..cb445939 100644 --- a/tests/test_owner_case_purge_contract.py +++ b/tests/test_owner_case_purge_contract.py @@ -153,9 +153,28 @@ def test_invocation_matrix_paths_counts_hash_and_boundaries() -> None: assert all(row == by_id[row["technique_id"]] for row in matrix[key]) for bucket in matrix["migration_batches"].values(): assert all(row == by_id[row["technique_id"]] for row in bucket) + # 原值:矩阵里每个 sample_files 路径都必须存在 + # 新值:scripts/extended_dashas.py 必须不存在,由 scripts/dasha_registry.py 接替; + # scripts/conditional_dashas.py 必须不存在,由 dwisaptatisama / shattrimshatsama / + # dwadashottari 三个现行模块接替。其余路径仍必须存在。 + # 原因:BUG-1341 删除了这两个占位文件。矩阵是历史归档,不改 JSON,也不把旧文件加回来。 + # test_historical_artifacts_are_byte_preserved_not_refreshed 只管另一份封存归档,不管这份清单。 + deleted_placeholders = { + "scripts/extended_dashas.py": ("scripts/dasha_registry.py",), + "scripts/conditional_dashas.py": ( + "scripts/dwisaptatisama_dasha.py", + "scripts/shattrimshatsama_dasha.py", + "scripts/dwadashottari_dasha.py", + ), + } for row in rows: for paths in row["sample_files"].values(): - assert all((ROOT / path).is_file() for path in paths) + for path in paths: + if path in deleted_placeholders: + assert not (ROOT / path).is_file() + assert all((ROOT / successor).is_file() for successor in deleted_placeholders[path]) + else: + assert (ROOT / path).is_file() for key in ("kp_exact_cusp", "kp_star_sub_sub", "timing_holdout", "saham", "tajika", "gulika", "sphuta", "prashna"): assert by_id[key]["claim_status"] == "blocked_or_observation_only" assert by_id[key]["commercial_sync_policy"] == "sync_observation_or_boundary_contract_only"