Files
Jyotisha/docs/tasks/PROGRESS-rectification-cross-midnight-gate-fix-20260920.md
T
jesse-uxandClaude Code 3f39bafc4a
Independent Staging Quality Gate / validate (push) Successful in 12m48s
Independent Staging Quality Gate / publish (push) Successful in 14m50s
docs: record staging authentication blocker before BUG-984
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-20 15:15:52 +08:00

99 lines
11 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.
# PROGRESS · 跨午夜门禁浮点断言修复(2026-09-20)
## 2026-09-20 独立 review 后交付追加
产品已提供第三套独立 Linux/Python 3.13 环境复验并允许合入,证据在 staging `0ca3871d` 的任务索引:定向 18 项通过,回退同日 3 绿/跨午夜相关 4 红,校正 glob 200 → 216 全绿。BUG-985 改 resolved,旧双机缺口解除;下文保留原执行时历史。同步 `a3577ce2` 时缓存补单按产品要求完整取 staging 版(已吸收原分支六行),不丢策略 b 授权。此次仅交付已 review 通过的原核心修复与测试修复,BUG-984 随后另树执行,不宣称生产端到端完成。
### 本次合入结果:认证阻塞,未交付
本地整合提交 `b27d4de963f9ba7c4072233cabe06c6875eb0582`;前置 bridge 复测 9 passed。`git push origin HEAD:staging` 返回 `Failed to authenticate user`,随后 `ls-remote` 证实远端仍 `a3577ce2fa0bfa6047d397e50ed2e676c58a4420`。前述“本次交付”是目标而非成功结果;当前未交付、未部署。BUG-985 测试缺陷仍可据第三环境验证标 resolved,BUG-984 按任务规定等前置合入后再实施。恢复本人 Git 写入认证后继续,不借凭据、不绕过串行约束。
## 基线、范围与交付
- 执行单:`TASK-rectification-cross-midnight-gate-fix-20260920.md`(F1–F4)。用户要求同步代码执行该单,不扩大到 BUG-984 缓存实施。
- fetch 后远端 `origin/staging = 1b646659e7c0dc07051b00d7e5c48633dee8498c`;按单从 `aa46da1016ffda65e4224af444a23710e084474a` 建独立工作树 `codex/rectification-cross-midnight-gate-fix-20260920`,再合并最新 staging 得到验证基线 `777bd53d`。仅四份文档有冲突,保留双方记录及最新 review 结论;没有覆盖主检出的未跟踪文件,没有 stash,也没有重写别的分支。
- BUG 编号核对:远端 staging 最大 980,原实现最大 984;本轮使用 985。
- 本轮仅改两个 Python 测试文件及任务/验收记录;相对 `777bd53d`,`scripts/`、前端、数据库、Skill、历史 golden、冻结报告与打分常数均不改。同步提交带入的其他前端改动来自已在 staging 的提交,不是本单改造。
- 尚未推送 staging、未部署;BUG-981 端到端仍受 BUG-984 阻塞。不能用本单测试结果宣布生产跨午夜问题全部解决。
## F1 · 同进程新旧路径逐位对照
- 保留原测试名和三个 ordinal,每例仍覆盖 121 分钟。
- A 使用真实引擎正常 contexts;B 复用同一批 contexts,只在 `scoring_service.merge_transition_proximity` 调用边界去掉 `candidate_at`,交给生产 helper 既有 legacy 回退路径。主事件引擎本身需要该字段,不能在主矩阵入口直接删除。
- 检查候选完整时间序列与窗口一致、所有候选日期等于请求日期、legacy 边界被调用且收到 121 项。最终分数及贡献矩阵均做 canonical JSON 字节严格相等,不使用容差或硬编码浮点哈希。
- 既有防复发核查:BUG-733 的 memoization docstring、同进程四层缓存差分和分档 golden 比较仍在;BUG-712 的坐标量化及缺 golden 失败测试仍在。此次是 BUG-733 同形复发,原规则只约束既有测试,没有阻止新文件引入绝对哈希。
### 既有断言变更三栏
| 原值 / 方式 | 新值 / 方式 | 原因 |
| --- | --- | --- |
| 三个 ordinal 各等于某台机器预先生成的分数 SHA-256 | 同一进程 A 新路径与 B 生产 legacy 路径,121 个分数 canonical 字节严格相同;另加整份贡献矩阵字节相同 | 要守的是“同日新旧不变性”,不是跨机器浮点字节一致;没有加容差、skip 或删除场景 |
| 窗口内只有一个日期 | 该日期集合恰等于请求 `birth_date`,且真实 contexts 时间序列等于窗口枚举 | 防止单日但锚点错误时 A/B 无意义 |
## F2 · 快速门桥接
保留 re-export 并在文件顶部说明用途与重复计数:单独运行源文件或 `test_rectification_*.py` 中的 bridge,各为 9 项;两者同时选择为 18 项,但只有 9 个独立场景。未移除 quick glob 的覆盖,也不把重复项记成新增测试。
## F3 · 时段扫描调用链与 BUG-984 定级
**确认可达,因此 BUG-984 是 BUG-981 端到端验收阻塞项。** 限定为证据未变且尚未触发三轮转分钟的历史跨午夜时段缓存命中;新建、无缓存或证据改变会进入已修路径。未修改缓存策略或 SQL。
| 层 | 符号及基线行号 | 证据 |
| --- | --- | --- |
| 前端分支 | `frontend/src/lib/rectification-agentic/v9/score-persist.ts:154,177–192`,`scoreAndPersistCurrentEvidence` | 旧缓存只比较证据指纹即可返回;未命中调 `runV9BlockScan`;版本探测在分钟分支 266 行 |
| HTTP 客户端 | `frontend/src/lib/rectification-agentic/v9/engine-client.ts:1021–1032,685–720` | POST `/api/rectification/v5/block_scan`,携带日期、时间窗、事件和步长 |
| API 注册/入口 | `scripts/jyotish_api_server.py:3562–3563,9100–9105` | `_compute_rectification_v5_block_scan` 规范化后调用服务 |
| 时段扫描 | `scripts/rectification/api_service.py:449–461,467–508` | `block_scan` 调 `score_candidates`,段支持率消费其候选分数 |
| 评分 | `scripts/rectification/api_service.py:211–214` | 调 `build_event_contribution_matrix` 和 `score_from_matrix` |
| 矩阵 | `scripts/rectification/scoring_service.py:237–250,295–303` | 生成真实 contexts,并调 `merge_transition_proximity` |
| 日期来源/应用 | `scripts/active_rectification_event_engine.py:90–103,593,608–614`;`scripts/rectification/dasha_transition_proximity.py:155–182` | 跨日枚举保留 `candidate_at`,已修 helper 从它取日期用于计算及缓存键 |
窗口核对:`declared-birth-window.ts:19–35,131–145`、`search-window.ts:16,38–60,193–206`、`case-service.ts:133–172`。
| 无申报钟点的路径 | 窗口 | exclusive span | 阶段 | 本身跨日期 |
| --- | --- | ---: | --- | --- |
| late_night | 23:00–03:59 | 299 分钟 | block_scan | 是 |
| unknown | 00:00–23:59 | 1439 分钟 | block_scan | 否 |
`unknown` 首轮的 late_night 分组只筛同日钟点,不把候选移到次日(`api_service.py:416–431,476–480`);后续选中跨午夜窗再重算才进入跨日触发范围。原修复单把两者均称作容易跨午夜的论据不够精确,本轮按源码明确此边界。
分钟防线仍在 `engine-client.ts:425–454`,既有回归 `rectification-engine-convergence.test.ts:94–124`、`rectification-engine-version-cross-midnight.test.ts:68–109`;它们不覆盖时段提前返回。回执 started/completed 的来源不同,聚合 SQL 仍取 `max(engine_version)`,本轮仅源码核查,未作数据库实测声明。已把结论写入 BUG-984 与缓存补单 §0。
## 验证
### 环境与可复现边界
- Windows 主机:Python 3.11.7,pyswisseph `20230604`,无项目 `.venv`,使用系统 `python`;原 `python3` launcher 不可用。
- 同主机隔离 Linux Docker:Python 3.13.15、glibc 2.36,pyswisseph `20230604`,镜像 `python:3.13-bookworm`。从验证基线 Git archive 解包两份 `/work/base`、`/work/fix`,只向后者覆盖两个测试文件。按仓库 `requirements.txt` / `requirements-dev.txt` 安装完整 Python 依赖;没有改仓库依赖、workflow,没有发布端口或挂载宿主 Docker socket。
- Linux 原测试 ordinal 2/3 失败,Windows 原测试全绿,已实证两个环境的浮点行为不同。**但这是同一物理机器上的 Windows/Linux 两个运行环境,不冒充任务书要求的两台独立机器。另一台 Linux 机器/runner 的同 SHA 复验仍属环境缺口。**
| 验证 | Windows 基线 | Windows 修复 | Linux 基线 | Linux 修复 |
| --- | ---: | ---: | ---: | ---: |
| 原文件 + bridge | 18 通过 | 纳入下行 | 14 通过 / 4 失败(ordinal 2/3 × bridge) | 纳入下行 |
| 原文件 + bridge + memoization | — | 32 通过 | — | 32 通过 |
| `tests/test_rectification_*.py` | 216 通过 | 216 通过 | 214 通过 / 2 失败 | 216 通过 |
| 内存回退日期修复 | — | 3 同日通过 / 1 跨午夜失败(预期红) | — | 3 同日通过 / 1 跨午夜失败(预期红) |
| quick(Linux 为其中 Python 步,未进入前端步骤) | 缺 mcp,退出 1 | 同一失败 | 881 通过 / 6 失败 / 5 跳过 | 883 通过 / 4 失败 / 5 跳过 |
| Linux 归档补 Git 索引后定向复验隐私/七政 | — | — | 65 通过 / 1 失败 | 65 通过 / 1 失败 |
- Windows quick 两侧均在 `interpretation_source_inventory_gate.py` 导入处报 `ModuleNotFoundError: No module named 'mcp'`;缺失引用输出逐项相同,不标通过。
- Linux quick 两侧均退出 1,未进入前端步骤。基线独有两个失败正是 ordinal 2/3;修改版的四个失败均属于基线,**新增失败 0**。共同失败逐项为:`test_qizheng_api_productization.py::test_qizheng_endpoint_returns_eleven_bodies_and_twelve_palaces`(400 != 200)、`test_repo_privacy_markers.py::test_tracked_repository_has_no_privacy_markers`、`::test_local_python_venv_is_not_tracked`、`::test_gitignore_covers_venv_symlink_name`(后三项为 archive 未带 Git 元数据)。
- 为核实归档缺口,在两份隔离目录初始化仅本地 Git 索引、按宿主真实 `git ls-files -z` 清单追踪,不提交/推送,重跑隐私及七政文件:两侧均 65 通过/1 失败,三项 Git 缺口解除,七政 400 的失败仍逐条相同。没有修改测试或越界修七政;未重跑完整 quick,不能把这次定向补验合成为“快速门全绿”。
- 独立只读审查未发现阻塞代码问题;审查方另实跑原文件 9 passed、bridge 9 passed,确认 quick 的校正 glob 收集 216 项,本组仅 9 项;原文件与 bridge 同时选择才重复到 18,不将旧任务书所述“同 glob 重复”当成本轮实测事实。
- 开工预检:远端 verified;focused 的历史镜像路径断言失败,与错误台账已知缺口一致,不制造 `.workbuddy` 目录消红。
- 回退验收通过独立进程内编译替换 helper 的日期表达式实现,仅内存中令 `candidate_date = birth_date`,没有编辑红线生产文件。两环境均三个同日 ordinal 绿、真实跨午夜矩阵断言红。
- 定向日志、Windows quick/glob 基线对照日志保留在本机会话临时目录;Linux `/tmp/{base,fix}-*.log` 已复制到宿主临时目录后停止本轮容器,容器保留供复核,不占用运行资源。只落统计、符号和环境信息,不复制请求体或出生资料。
- 最终将本轮文件加入 Git 索引后实跑 `python -m pytest tests/test_repo_privacy_markers.py -ra`:62 passed。`git diff --check` 通过;生产红线、历史 golden 与 references 相对 `777bd53d` 零差异,测试文件硬编码 64 位分数哈希为零。
## 验收状态
| 项目 | 结论 |
| --- | --- |
| F1 断言实现、双浮点环境、回退对照 | 本地验证通过;两台独立机器要求仍为环境缺口 |
| F2 快速门覆盖与重复计数说明 | 通过 |
| F3 调用链查证与定级 | 通过;BUG-984 另单实施,未关闭 |
| F4 记录与独立复核 | 通过:BUG-981/984/985、补单 §0、状态板、BLOCKED 与补验清单已更新;独立审查无阻塞发现且两个文件分别 9 项通过 |
| staging 合入、门禁、部署 | 尚未执行,不声称已交付 |
补验清单:`docs/testing/rectification-cross-midnight-gate-fix-20260920.md`。不新增用户可感知行为,本轮不新增 CHANGELOG 条目。