fix(rectification): 候选分钟不变量记忆化(BUG-721)
Shadbala / Ashtakavarga / Dasha 时间轴进 static context;过境盘按事件日期缓存 chart;探针网格相同时只算一次。打分与决策回执与基线 golden 逐字相同(剔除计时字段)。
This commit is contained in:
+16
-1
@@ -11206,6 +11206,22 @@
|
||||
- 复发自:无
|
||||
- 修复版本:待发布
|
||||
|
||||
## BUG-721 | 生时校正把候选分钟不变量放在事件循环里重复计算
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-09-15
|
||||
- 最近更新:2026-09-16
|
||||
- 影响面:`scripts/active_rectification_event_engine.py`、`scripts/rectification/scoring_service.py`、`scripts/rectification/refinement_packet.py`
|
||||
- 用户现象:每记一条证据或答一道题都要重算 `POST /api/rectification/v5/score`,等待明显偏长。不是回归,也不是结果算错。
|
||||
- 触发条件:一次请求里有多个候选分钟,并且事件带 year/month 采样(采样日把候选×事件再放大)。
|
||||
- 根因:`build_candidate_static_context` 引入后,排盘/分盘按候选分钟只算一次,但 Shadbala、Ashtakavarga、Vimshottari 时间轴、Narayana 周期表仍留在 `_candidate_row` 的事件循环里,被「候选 × 事件 × 采样日」三重放大。过境盘只依赖事件日期,却按候选分钟在最内层重算。`build_refinement_packet` 在 `probe_times == grid_times` 时对 `_discriminating_event_probe_lists` 算两遍。`scoring_service._cached_rows` 是加错层的死代码,生产入口从不走。
|
||||
- 修复:把候选分钟不变量挂进 static context,过境盘在 `compute_event_candidate_rows` 调用栈内用局部字典按日期缓存 chart(规则判定仍按候选算),探针在时间网格相同时复用一次结果;删掉 `_cached_rows`。不改算法、权重、阈值、采样规则,也不修 static context 里 Shadbala 的 `birth_minute` 双算。
|
||||
- 验证:基线 `a8d29d1b` 真实跑出 golden(公开 1990-01-01 北京烟测盘 + 虚构事件);改后 `candidate_scores` 与剔除 `column_compare_ms` 的 `decision_receipt` 逐字相同。计数断言:`calc_shadbala` / `calc_ashtakavarga` / `build_dasha_timeline` / `calc_narayana_mahadasha` 在引擎打分路径上各等于候选分钟数;过境 `compute_chart` 等于去重事件日期数;year 精度过境仍早退 `[]`;默认探针路径 1 次、`refresh_probes` 且 refresh 列存在时 2 次。
|
||||
- 防复发:新增的候选分钟不变量必须进 static context,不得留在 `_candidate_row` 的事件循环里;新增的事件不变量不得按候选迭代。记忆化只允许请求内显式传递的 context / 局部字典,禁止模块级 `lru_cache` 跨请求持有出生资料派生数据。
|
||||
- 相关记录:无
|
||||
- 复发自:无
|
||||
- 修复版本:待发布
|
||||
|
||||
## BUG-722 | 意图分类器两次异常被说成用户没说清,经历被丢掉
|
||||
|
||||
- 状态:resolved
|
||||
@@ -11253,4 +11269,3 @@
|
||||
- 相关记录:BUG-059、BUG-388
|
||||
- 复发自:BUG-059(总预算约束);BUG-388 的防复发只写了单次尝试,因此没拦住
|
||||
- 修复版本:待发布
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# PROGRESS · 重算记忆化(2026-09-15 / 执行 2026-09-16)
|
||||
|
||||
- 执行分支:`codex/rectification-engine-memoization-20260915`
|
||||
- 工作树:`.worktrees/rectification-engine-memoization-20260915`
|
||||
- 任务书基线:`6b3248bf`(已被后续合入)。本机开工 `HEAD` = `origin/staging` = `a8d29d1b`
|
||||
- BUG:`BUG-721`(落库时最大号仍是 720,未顺延)
|
||||
|
||||
## 开工前置
|
||||
|
||||
| 项 | 结果 |
|
||||
| --- | --- |
|
||||
| `git status -sb` 第一行 | `## codex/rectification-engine-memoization-20260915...origin/staging` |
|
||||
| `HEAD` | `a8d29d1b` |
|
||||
| BUG_HISTORY 检索 | `重复计算` / `shadbala` / `scoring_service` / `_cached_rows`:无同模块分层遗漏记录。最大号 BUG-720 |
|
||||
| 本机 Python | 主仓 `.venv` 是 25 字节指针。本 worktree 用 Anaconda 3.11.7 `--system-site-packages` 建真实 venv,复用已有 `pyswisseph 2.10.3.2` / swisseph `20230604`,未升级该包 |
|
||||
| 基线 golden | 改代码前用 `a8d29d1b` 真实跑出 `tests/golden/rectification_engine_memoization_v1.json`。golden 测试改前绿 |
|
||||
|
||||
未改 `docs/tasks/README.md` 状态列。未推 staging。未改 `jyotish_api_server.py`、前端、`sample_event_dates`、`_SWISSEPH_LOCK`。
|
||||
|
||||
## 做了什么
|
||||
|
||||
6.1–6.6 全做,未按 §8 让步砍项。
|
||||
|
||||
| 条 | 做法 |
|
||||
| --- | --- |
|
||||
| 6.1 | `build_candidate_static_context` 把已算的 `ashtakavarga_result` / `shadbala_result` 挂进 context。辅助函数只读结果做判定。Shadbala 只复用 `sthana_bala.total` / `drik_bala` / `naisargika_bala`;测试证明带/不带 `birth_minute` 这三项相等。`birth_minute` 双算不修(§4.3) |
|
||||
| 6.2 | Vimshottari 时间轴、Narayana 周期表进 context;`_active_vimshottari` / `_active_narayana` 只留 `find_current` / `get_current_narayana_dasha` |
|
||||
| 6.3 | `compute_event_candidate_rows` 内局部字典按事件日期缓存过境 **chart**;规则仍按候选算。`precision == "year"` 仍早退 `[]` |
|
||||
| 6.4 | `probe_times == grid_times` 时 `discriminating_event_probe_set` 结果复用给 contrast;`refresh_probes` 且 refresh 列存在时仍两次 |
|
||||
| 6.5 | 删除 `scoring_service._cached_rows`。`_canonical` 仍被 `sha256` 使用,保留 |
|
||||
| 6.6 | 公开 1990-01-01 北京烟测盘 + 虚构事件。golden 由基线代码跑出,禁止手造 |
|
||||
|
||||
记忆化只在请求内:static context dict,以及 `compute_event_candidate_rows` / `build_refinement_packet` 栈内局部字典。无模块级跨请求缓存。
|
||||
|
||||
## 测试
|
||||
|
||||
定向(任务书 §9 + 本单新文件):
|
||||
|
||||
| 套件 | 结果 |
|
||||
| --- | --- |
|
||||
| `tests/test_rectification_engine_memoization.py` | **10 passed** |
|
||||
| `test_rectification_v5_services.py` 等 7 个任务书名单 | 与本单文件合计 **129 passed** |
|
||||
| quality-gate quick 的 pytest(含 `tests/test_rectification_*.py`) | **776 passed, 1 skipped**(575.78s) |
|
||||
|
||||
本机 `run_quality_gate.py --profile quick` 在 pytest 之后的 `npm test` 失败:`tsx` 不在 PATH(Windows 前端环境缺口)。本单未改前端,不把这条写成通过。
|
||||
|
||||
未改任何既有断言的期望值。测试总数高于开工时(新增 10 条)。
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
未改。纯内部记忆化,用户可见打分与决策回执逐字不变(计时字段除外)。
|
||||
|
||||
## 偏离
|
||||
|
||||
- 任务书写 `.venv/bin/python`,本机换成 `.\.venv\Scripts\python.exe`。
|
||||
- golden 测试只锁 `candidate_scores` 与剔除 `column_compare_ms` 的 `decision_receipt`(6.6 原文)。`candidate_feature_snapshot` 写进 golden 文件备查,不作为 pytest 硬断言:KP/Hora 指纹在 pytest 全量收集下会出现第二条稳定哈希,与打分无关。
|
||||
- 未 `git push origin HEAD:staging`。
|
||||
|
||||
## 观察项(不修)
|
||||
|
||||
`build_candidate_static_context` 的 Shadbala `birth_hour = hour + minute/60` 同时又传 `birth_minute`,只流进 fingerprints,本单照搬。
|
||||
Reference in New Issue
Block a user