test(report): lock binding exclusion allowlist literals (BUG-694)
Independent Staging Quality Gate / validate (push) Successful in 9m52s
Independent Staging Quality Gate / publish (push) Successful in 2m6s

Contract-test the D2 exclusion tuples so widening them cannot silently pass. Record the timezonefinder quality-gate gap in BLOCKED.md.
This commit is contained in:
jesse-ux
2026-09-15 10:41:10 +08:00
parent 10b463b9e8
commit 8d56d0ab0b
5 changed files with 95 additions and 2 deletions
+15
View File
@@ -1,5 +1,20 @@
# BLOCKED
## 快速门 timezone 推断依赖(2026-09-15,对照 `039b0a26` / `1d2aeffa`
- **`run_quality_gate.py --profile quick` 必红一条,不是 BUG-693/694 的回归。** 验收机在 `1d2aeffa``739 passed, 1 failed`;同一条在修复前的 `039b0a26` 上同样红。
- 失败测试:`tests/test_api_server_security.py::test_shadbala_endpoint_returns_ranked_planet_strength`
- warning 原文:`WARNING [api_server] shadbala advanced layer failed: timezone inference dependency unavailable`
- 断言:`assert ['core_sixfold'] == ['core_sixfold', 'advanced_evidence']`(缺 `timezonefinder`,高级层没挂上)。
- 本机口径:快速门通过 =「除这一条外全绿」。谁要宣称快速门全绿,必须先在该环境装上 `timezonefinder``requirements.txt` / `pyproject.toml` 已声明 `timezonefinder>=6.5`)。不得改这条断言来让门变绿。
复现:
```bash
python -m pytest tests/test_api_server_security.py::test_shadbala_endpoint_returns_ranked_planet_strength
python scripts/run_quality_gate.py --profile quick
```
## 采集流程重设计(2026-09-10,分支 `codex/rectification-collection-redesign-20260910`
- **`next build` / 首屏 gzip 未核。** 本 worktree 的 `frontend/node_modules` 是指向主仓的软链。实测 `npm run build` 在 Next 16.3.1 Turbopack 失败:`Symlink [project]/frontend/node_modules is invalid, it points out of the filesystem root`。不得把 `/` Static 或 gzip ±2% 写成通过。
+1 -1
View File
@@ -10801,7 +10801,7 @@
- 根因:被哈希的载荷含墙钟字段(`elapsed_seconds`、分阶段耗时、VedAstro `called_at` / cache 时间)。`kendra_lords``list(set(...))` 生成,跨进程顺序不稳定。
- 修复:`binding_scope` 显式排除自引用(`report_quality_gate``shared_full_report_authority`)、生成时刻(`generated_at` 以及 `**.called_at` / `**.cache_created_at` / `**.cache_expires_at`)、墙钟耗时(`**.elapsed_seconds`)。业务字段仍输出。Kendra / trikona lords 改为排序后的稳定列表。
- 验证:同输入两次构造 `result_hash` 相同;只改 `elapsed_seconds` 不变;改 `coverage` 必变。虚构盘三次 CLI 哈希 `2f4739a4…` 全同,内部 `elapsed_seconds` 仍为 2.74 / 2.86 / 2.83。
- 防复发:排除集只能是自引用 / 生成时刻 / 墙钟三类,必须写进回执并由质量门重算。加第四类要改任务书。
- 防复发:排除集只能是自引用 / 生成时刻 / 墙钟三类,必须写进回执并由质量门重算。加第四类要改任务书。允许集有字面量合同测试守门,改动必须先过测试再改任务书。
- 相关记录:BUG-693、BUG-576
- 复发自:无
- 修复版本:待发布
@@ -0,0 +1,51 @@
# 进度 · 绑定排除集字面量锁 + timezone 缺口入账(2026-09-15
## 范围
- 分支:`codex/report-binding-scope-lock-20260915`(基于 `origin/staging` @ `10b463b9`
- 任务单:`docs/tasks/TASK-report-binding-scope-lock-20260915.md`
- 不新增 BUG 编号;只补强 BUG-694 防复发条
- 生产代码一行未改(`calculation_profile_contract.py` / `full_report_quality_gate.py` / `jyotish_engine.py`
- `CHANGELOG.md` 不写(D5
## 完成
- T1`test_binding_exclusion_allowlist_is_the_literal_d2_set` 钉死两个常量的完整字面量与顺序。注释写明三类归属,以及改这里要先改任务书并在 BUG-694 补记。
- T2`BLOCKED.md` 记 timezone 缺口;本机复现同一条测试红,warning 原文一致。未改该断言。未装 `timezonefinder`(仓内已声明,本机 Anaconda 没有;装上只绿本机,不改变验收机缺口)。
- T3:BUG-694 防复发条补了一句字面量合同测试守门。
## 任务 1 红 / 绿
`ALLOWED_BINDING_EXCLUDED_PATHS` 临时加 `"**.generated_by"`
```
FAILED tests/test_calculation_profile_contract.py::test_binding_exclusion_allowlist_is_the_literal_d2_set
AssertionError: assert ('ai_and_audi...generated_by') == ('ai_and_audi...e_expires_at')
Left contains one more item: '**.generated_by'
RED_EXIT 1
```
恢复常量后:
```
. [100%]
GREEN_EXIT 0
```
`git diff scripts/calculation_profile_contract.py` 为空。
## 定向测试
`tests/test_calculation_profile_contract.py` + `tests/test_full_report_quality_gate.py`:全绿(既有 3 skipped)。
## `--profile quick` 失败清单
验收机(任务书 §1.2):`739 passed, 1 failed`
```
FAILED tests/test_api_server_security.py::test_shadbala_endpoint_returns_ranked_planet_strength
WARNING [api_server] shadbala advanced layer failed: timezone inference dependency unavailable
assert ['core_sixfold'] == ['core_sixfold', 'advanced_evidence']
```
本机隔离复现同一条,warning 原文相同。本机没有项目 `.venv`Anaconda 还缺 `mcp`,完整 `run_quality_gate.py --profile quick` 会先在 `interpretation_source_inventory_gate` 红掉,跑不到 739 那条汇总;timezone 缺口以隔离命令为准,见 `BLOCKED.md`
+1 -1
View File
@@ -137,7 +137,7 @@
| `TASK-report-chart-render-20260909.md` | `PROGRESS-report-chart-render-20260909.md` | 报告页所有分盘标题下空白:引擎 22 张 `<svg>``skipHtml` 丢弃(09-06 Markdown 直渲回归)。引擎旁加 ```jyotish-chart 围栏 JSON,前端 zod 校验后用自绘北印式组件全部渲染;不放开原始 HTML | 已验收(2fdcb14f):tsc/lint 0 error、chart 测试 29/29、`/` Static、gzip +0.96%;围栏构造在 try 外的 P2 并入 `TASK-upstream-sync2-fix-20260909.md` 任务 3 | `codex/report-chart-render-20260909`BUG-607 |
| `TASK-report-chart-layout-fix-20260909.md` | `PROGRESS-report-chart-layout-fix-20260909.md` | 星盘渲染回归修复:22 张北印盘全部重叠(浮动 + 负 margin 凑两栏对连续多对无效)+ 滚动时 `components` 每渲染新建导致整篇报告卸载重建、页面卡;改 rehype 成组进既有两栏 grid、文章树 `useMemo`、目录状态下沉 | 待验收 | `87daffe2`BUG-616/617);已 merge origin/staging `df090fd5` |
| `TASK-report-provenance-binding-20260915.md` | `PROGRESS-report-provenance-binding-20260915.md` | 专业报告溯源绑定:`result_binding` 只绑到中间态包(实测 18/36 个顶层键、6.24 MB / 交付 10.04 MB),`full_report_pack`、`chart_identity`、`timing_precision_contract` 等全在覆盖外,而质量门只比自洽所以恒 passed(BUG-693);被哈希的载荷含墙钟 `ai_and_audit.summary.elapsed_seconds`,同一输入两次跑出不同 `result_hash`(BUG-694)。末尾按交付对象重绑 + 显式排除集写进回执 + 质量门补覆盖校验;上游 09-14 的有界投影实测收益 < 0.1 秒,不抄 | 已验收(`1d2aeffa`):三次 CLI + 三个 `PYTHONHASHSEED` 哈希全同、变异法验证覆盖 33/40 键、耗时中位数 2737 ms(修复前 2769 ms)、`npm test` fail 27 = 基线;快速门唯一红的 `test_shadbala_endpoint_returns_ranked_planet_strength` 在修复前同样红(timezone 依赖缺)。遗留补漏单 `TASK-report-binding-scope-lock-20260915.md` | `1d2aeffa` |
| `TASK-report-binding-scope-lock-20260915.md` | `PROGRESS-report-binding-scope-lock-20260915.md` | 验收补漏单:BUG-694 的「排除集只能三类」是纸面规矩——质量门与测试引用的是生产者同一对常量,往常量里加第四类会自动放行;把允许集的字面量钉进合同测试(改动即红)。另把 `--profile quick` 必红的 `timezone inference dependency unavailable` 记进 `BLOCKED.md`(修复前同样红,非回归)。不新增 BUG 编号,只更新 BUG-694 | 待领取 | |
| `TASK-report-binding-scope-lock-20260915.md` | `PROGRESS-report-binding-scope-lock-20260915.md` | 验收补漏单:BUG-694 的「排除集只能三类」是纸面规矩——质量门与测试引用的是生产者同一对常量,往常量里加第四类会自动放行;把允许集的字面量钉进合同测试(改动即红)。另把 `--profile quick` 必红的 `timezone inference dependency unavailable` 记进 `BLOCKED.md`(修复前同样红,非回归)。不新增 BUG 编号,只更新 BUG-694 | 待验收 | `codex/report-binding-scope-lock-20260915` |
### 前端基础与工程
@@ -542,6 +542,33 @@ def test_direct_script_and_package_import_are_functionally_equivalent() -> None:
assert module.build_calculation_profile(BIRTH_PAYLOAD) == build_calculation_profile(BIRTH_PAYLOAD)
def test_binding_exclusion_allowlist_is_the_literal_d2_set() -> None:
"""Lock the allowlist so widening it cannot silently go green.
Three classes only (BUG-694). Adding a fourth class, renaming a path, or
dropping one must fail this test until the task book and BUG-694 are
updated. The quality gate imports the same constants, so a lock here is
the only check that fails when the producer set grows.
自引用: ``report_quality_gate``, ``shared_full_report_authority``.
生成时刻: ``generated_at``; ``**.called_at`` / ``**.cache_created_at`` /
``**.cache_expires_at``.
墙钟耗时: ``ai_and_audit.summary.elapsed_seconds`` and ``**.elapsed_seconds``.
"""
assert ALLOWED_BINDING_EXCLUDED_TOP_KEYS == (
"generated_at",
"report_quality_gate",
"shared_full_report_authority",
)
assert ALLOWED_BINDING_EXCLUDED_PATHS == (
"ai_and_audit.summary.elapsed_seconds",
"**.elapsed_seconds",
"**.called_at",
"**.cache_created_at",
"**.cache_expires_at",
)
REQUIRED_DELIVERED_KEYS = (
"full_report_pack",
"chart_identity",