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
8.1 KiB
8.1 KiB
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-21import 同一对常量,: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. 硬红线
- 不改生产代码。
scripts/calculation_profile_contract.py、scripts/full_report_quality_gate.py、scripts/jyotish_engine.py一行不动。若发现不改生产代码就锁不住,停下来写进度记录说明,不要自行改。 - 不得放宽或删除 BUG-693/694 的既有判据与断言。
tests/test_calculation_profile_contract.py+tests/test_full_report_quality_gate.py保持全绿;--profile quick除 §1.2 那条 timezone 缺口外不得新增失败。- 不改
.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. 让步顺序
- 若字面量锁与将来某次合法扩集冲突:先改任务书/BUG 记录,再改测试字面量,顺序不得颠倒。
- 若 timezone 依赖能在本机装上(需要联网或系统包),优先装上并让那条测试真绿,
BLOCKED.md只保留"曾经缺、现在已补"的一行说明;装不上再按任务 2 入账。 - 任何情况下不得通过修改
test_shadbala_endpoint_returns_ranked_planet_strength的断言来让门变绿。
7. 开工前置命令
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 failed(timezone)
8. BUG 编号起点
本单不新增编号(D5)。docs/BUG_HISTORY.md 当前最大号 BUG-694;只更新 BUG-694,不要占 695。若执行中发现真实回归,再按当时最大号 +1 新开。