Files
Jyotisha/docs/tasks/TASK-report-binding-scope-lock-20260915.md
T
Jesse_ChenandClaude Opus 5 10b463b9e8 docs(tasks): lock the binding exclusion list and record the timezone gap
BUG-693/694 实现(1d2aeffa)验收通过:三次 CLI 加三个 PYTHONHASHSEED 哈希
全同,变异法验证覆盖 33/40 顶层键,耗时中位数 2737 ms(修复前 2769 ms)。
补漏单处理两个没被机制挡住的洞:排除集的「只能三类」靠的是生产者、质量门、
测试引用同一对常量,加第四类会自动放行,改为把字面量钉进合同测试;快速门
必红的 timezone inference 依赖缺口记进 BLOCKED.md(修复前同样红,非回归)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
2026-09-15 02:34:37 +00:00

104 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TASK · 补漏单:把绑定排除集钉成字面量 + 记录 timezone 环境缺口 — 2026-09-15
- 基线:`origin/staging` @ `1d2aeffa`BUG-693/694 实现已合入并**已由我验收通过**)。
- 分支:`codex/report-binding-scope-lock-20260915`worktree `.worktrees/report-binding-scope-lock-20260915`
- 关联:`TASK-report-provenance-binding-20260915.md`(本单是它的验收补漏)、BUG-694(本单补它的防复发条)。
- 串行:只加一个合同测试 + 改 `BLOCKED.md`。**不改任何生产代码行为**,与在途分支无重叠。
## 1. 缘起(验收实证)
BUG-693/694 的实现验收通过:三次 CLI 加三个 `PYTHONHASHSEED` 哈希全同(`784cdda5…`),变异法独立验证覆盖 33/40 顶层键,耗时中位数 2737 ms(修复前 2769 ms)。本单不推翻其中任何一条。
验收时发现两个**没有被任何机制挡住**的洞:
### 1.1 排除集的"只能三类"目前是纸面规矩
BUG-694 的防复发条写的是「排除集只能是自引用 / 生成时刻 / 墙钟三类……加第四类要改任务书」。实际约束链是:
- 生产者:`scripts/calculation_profile_contract.py:81` / `:86` 定义 `ALLOWED_BINDING_EXCLUDED_TOP_KEYS` / `ALLOWED_BINDING_EXCLUDED_PATHS``:458` / `:459` 把它们原样写进回执。
- 质量门:`scripts/full_report_quality_gate.py:14-21` **import 同一对常量**`:197` / `:200` 拿回执里的排除集减去这对常量判「意外排除」。
- 测试:`tests/test_calculation_profile_contract.py:585-586` 断言 `set(scope[...]) == set(ALLOWED_...)`
三处引用的是同一个常量,所以**谁往常量里再加一条,门自动放行、测试自动变绿**。这条防复发现在只能挡住外来或手工篡改的包,挡不住它真正想挡的那件事(排除集悄悄变宽)。
本轮那次扩集就是例证:D2 原文只批了 `ai_and_audit.summary.elapsed_seconds` 一条墙钟路径,落地扩成了 `**.elapsed_seconds` 通配并新增 `**.called_at` / `**.cache_created_at` / `**.cache_expires_at`。理由(跨进程可复现)成立、也写进了 BUG-694,但任务书没有被改,也没有任何东西要求改。
### 1.2 `--profile quick` 在本机必红一条,没人记
```
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
E assert ['core_sixfold'] == ['core_sixfold', 'advanced_evidence']
```
`739 passed, 1 failed`。同一条在修复前的 `039b0a26` 上**同样红**,与 BUG-693/694 无关。`BLOCKED.md` 里没有这条;实现方进度记录里写的是自己机器缺 `mcp`,也没进 `BLOCKED.md`。结果是下一个人跑快速门会重新查一遍同一个环境问题。
## 2. 决策记录
| 决策 | 内容 |
| --- | --- |
| D1 | **不动现有排除集的内容。** 四条墙钟/时间戳路径按 BUG-694 的记录保留,本单不重新开会讨论它们该不该在里面。 |
| D2 | **把当前允许集的字面量钉进合同测试**:常量被改动(增、删、改名)即测试红,由人决定放不放行,而不是自动通过。这是本单唯一的行为约束。 |
| D3 | **不把这条做成运行时校验**(不在生产代码里再写死一份清单)——两份清单会漂移,且门在运行期要挡的是外来包,语义不同。锁在测试层。 |
| D4 | **`BLOCKED.md` 如实记录 timezone 缺口**,写明失败的测试名、warning 原文、以及"修复前同样红"这个对照证据。不得写成通过,也不得为了让门变绿去改那条断言。 |
| D5 | 不新增 BUG 编号。本单是 BUG-694 防复发条的补强,落在原记录上。 |
## 3. 硬红线
1. **不改生产代码。** `scripts/calculation_profile_contract.py``scripts/full_report_quality_gate.py``scripts/jyotish_engine.py` 一行不动。若发现不改生产代码就锁不住,停下来写进度记录说明,不要自行改。
2. 不得放宽或删除 BUG-693/694 的既有判据与断言。
3. `tests/test_calculation_profile_contract.py` + `tests/test_full_report_quality_gate.py` 保持全绿;`--profile quick` 除 §1.2 那条 timezone 缺口外不得新增失败。
4. 不改 `.gitea/workflows/**`,不提升 `main`
## 4. 任务分解
### 任务 1 · 允许集字面量锁(P1)
-`tests/test_calculation_profile_contract.py` 新增一条合同测试,断言两个常量的**完整字面量与顺序**等于当前值:
- `ALLOWED_BINDING_EXCLUDED_TOP_KEYS == ("generated_at", "report_quality_gate", "shared_full_report_authority")`
- `ALLOWED_BINDING_EXCLUDED_PATHS == ("ai_and_audit.summary.elapsed_seconds", "**.elapsed_seconds", "**.called_at", "**.cache_created_at", "**.cache_expires_at")`
- 测试里写明三类归属与"改这里要先改任务书并在 BUG-694 补记"的注释,不要只留一行断言。
- 验收标准:本地把常量任意加一条(例如 `**.generated_by`)→ 该测试红;恢复后绿。进度记录贴这两次的输出。
### 任务 2 · 环境缺口入账(P1)
- `BLOCKED.md` 新增一节,按 D4 写清:失败测试名、warning 原文、`739 passed, 1 failed` 的数字、以及"在 `039b0a26`(修复前)上同样红"这条对照证据,并注明**这不是 BUG-693/694 的回归**。
- 同时写明它对验收的影响:本机 `--profile quick` 的通过口径是"除这一条外全绿",谁要宣称快速门全绿,必须先补上 timezone 推断依赖。
- 验收标准:条目里能直接复制出复现命令;不出现"通过"字样。
### 任务 3 · 记录(P2
- `docs/BUG_HISTORY.md`**BUG-694**:更新「最近更新」日期,防复发条补一句——允许集有字面量合同测试守门,改动必须先过测试再改任务书。不新增编号、不改原有的现象/根因/修复正文。
- `docs/tasks/PROGRESS-report-binding-scope-lock-20260915.md`:贴任务 1 的红/绿两次输出与 `--profile quick` 的失败清单。
- `CHANGELOG.md` 不写(对用户不可感知)。
## 5. 不在本单范围(验收时记下的观察项,不要顺手改)
- `report_quality_gate` / `shared_full_report_authority` 现在挂在 `sanitize_professional_report_reference` 之后,不再过脱敏。实测差异只有 `limitation_reference: null` 这类空值被保留,无路径或内部字段泄漏,前端不消费这两个键。**本单不动**;要改需单独一单并说明"交付对象最后必过一遍 sanitize"这条保证要不要恢复。
- `cmd_yoga``list(set(...))``sorted(...)` 是 BUG-694 的第二根因修复,已记录在案,**不要回退**。
- BUG-692 那条线:候选数 = 1 时会出现「还剩 … 里 1 个候选。按现有信息分不开。」自相矛盾(修复前说「这两分钟」,同样错,不是回归)。属于 `TASK-rectification-invite-copy-and-assertions-fix-20260915.md` 的后续,不在本单。
## 6. 让步顺序
1. 若字面量锁与将来某次合法扩集冲突:先改任务书/BUG 记录,再改测试字面量,顺序不得颠倒。
2. 若 timezone 依赖能在本机装上(需要联网或系统包),**优先装上并让那条测试真绿**,`BLOCKED.md` 只保留"曾经缺、现在已补"的一行说明;装不上再按任务 2 入账。
3. 任何情况下不得通过修改 `test_shadbala_endpoint_returns_ranked_planet_strength` 的断言来让门变绿。
## 7. 开工前置命令
```bash
git -C /workspace/Jyotisha status -sb | head -1
git -C /workspace/Jyotisha fetch origin --prune
git -C /workspace/Jyotisha worktree add -b codex/report-binding-scope-lock-20260915 \
.worktrees/report-binding-scope-lock-20260915 origin/staging
cd .worktrees/report-binding-scope-lock-20260915
/workspace/Jyotisha/.venv/bin/python -m pytest \
tests/test_calculation_profile_contract.py tests/test_full_report_quality_gate.py
/workspace/Jyotisha/.venv/bin/python scripts/run_quality_gate.py --profile quick # 预期:739 passed, 1 failedtimezone
```
## 8. BUG 编号起点
**本单不新增编号**D5)。`docs/BUG_HISTORY.md` 当前最大号 BUG-694;只更新 BUG-694,不要占 695。若执行中发现真实回归,再按当时最大号 +1 新开。