fix(rectification): use candidate dates for cross-midnight dasha scoring
Add date-isolated caches and regression coverage, align scoring identity, and freeze full research reruns while preserving historical artifacts. Record unresolved cache/receipt identity and end-to-end acceptance gaps for branch review only. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
# PROGRESS · 跨午夜候选 Dasha 日期修复(2026-09-20)
|
||||
|
||||
## 基线、授权与边界
|
||||
|
||||
- 用户要求执行远端 `dacd4044` 的任务;fetch 时远端已追加产品决策补充 `03cba4780a220b132cf4f06d22e14608aaf9ad3c`,本轮以该后代为基线。
|
||||
- 任务:`TASK-rectification-cross-midnight-dasha-20260920.md`。产品决策 A/B/C 已放行:修复候选级日期、重新冻结重跑、通过 V9 `engine_version` 区分结果。
|
||||
- 工作树 `.worktrees/rectification-cross-midnight-20260920`;分支 `codex/rectification-cross-midnight-20260920`。上一轮已提交的独立工作树只作基线读取与测试,不更改其源码。
|
||||
- 开工核对 Bug 最大号为 980;本单使用 BUG-981。已与任务书会话确认其未修改相关生产文件、未占用编号。本会话各实现任务文件所有权分开。
|
||||
- 不改打分权重、确认门、Skill 版本、V4 `INPUT_CONTRACT_VERSION`、数据库结构、workflow、依赖、DNS 或 main。
|
||||
- 可选回执实现哈希增强不做;采用默认 `engine_version` 与既有后端 `ALGORITHM_VERSION` 同步 bump,保留原环境覆盖语义。线上环境是否覆盖另行验收,不借用凭据。
|
||||
|
||||
## 执行中纠正的任务书事实
|
||||
|
||||
任务书 §1.4 的 `BUG-3315` 实为历史文档行号,对应记录是 BUG-198;相关开窗记录另有 BUG-114 / BUG-353,不新增不存在的编号。候选枚举与时段映射回归仍在,未覆盖后来加入的日期辅助项。
|
||||
|
||||
T4 追踪发现:`v9EngineVersion()` 默认值主要用于 started/failed 回执;成功 compare / diagnostics 回执使用实际 `algorithmVersion`。`liveEngineScoringIdentityFromEnv()` 还会把非粗版本的环境覆盖视为算法身份,`cachedEngineScoreIsReusable()` 已有算法身份相等比较,`score-persist.ts` 在身份与输入相同时可直接复用旧分数。因而任务书“全仓只写不比”并不准确,只改默认串不足以落实产品 C,甚至可能继续使用错误的缓存分数。
|
||||
|
||||
最小实现选择:在本单允许的 `scoring_service.py` 将既有 `ALGORITHM_VERSION` 从 `rectification-v5-matrix-scoring-7` 提升为 `rectification-v5-matrix-scoring-8`,前端默认标记同步;复用既有失效逻辑,不新增按版本拒绝打开历史会话的门,不修改 Skill、V4 input contract、SQL 或旧回执。成功结果保留实际来源身份,不能把旧缓存强行重新标成新版。环境若覆盖旧算法身份,部署验收仍需核实;没有受控访问时列为缺口。
|
||||
|
||||
## 必读与预检
|
||||
|
||||
已读错误台账、分钟分辨率研究结论、前轮偏差报告、任务书和 BUG-098 / 427 / 428 / 621 / 978 / 979 / 980。旧 BUG-098 的跨午夜保护针对候选枚举,不足以覆盖后来加入的 transition-proximity 日期参数;BUG-427/428 的实现归属与曝光边界继续有效。
|
||||
|
||||
本机运行 `python scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45`:实际 Python 3.11.7,有 pytest;无本工作树 `.venv`。远端 verified、碎片与适配器检查成功;focused tests 因既有 `test_preflight_fragment_scan_reports_authority_layers_and_risk_buckets` 的 `.workbuddy` 镜像路径断言失败。与前轮台账一致,不冒写预检全绿。
|
||||
|
||||
## 执行与验收结论
|
||||
|
||||
核心日期修复、重新冻结及完整重跑完成;T4 缓存/回执身份仍未闭环,因此整单未通过完整验收。产品随后要求“按分支推送,我远程 review”,本轮仅向独立分支 `codex/rectification-cross-midnight-20260920` 交付供评审,推送结果以远端 SHA 核对为准;不合入 staging,不部署,不以其他会话的 staging 部署证明本轮已发布。保留原测试基线 `03cba478`,不混入同期其他任务的提交。
|
||||
|
||||
| 项目 | 状态 | 证据/下一步 |
|
||||
| --- | --- | --- |
|
||||
| T1 修复前红测 | 通过 | 原实现 4 failed / 4 passed,包含跨年、闰日、一般午夜日期/缓存及真实引擎回归;同日 golden 原来即通过 |
|
||||
| T2 最小生产修复 | 核心日期修复通过;部署未验收 | 19 个同日窗口共 2299 候选分数与矩阵字节相同;真实跨日全 121 候选等于日期正确独立计算;性能中位 -0.87%;独立生产选择性测试 4 项通过 |
|
||||
| T3 冻结及重跑 | 完成,独立校验通过 | 900 组合与 20 例均完整重跑,旧新逐例变化均为 0;独立复算真实源码身份、历史字节、汇总与 Markdown 45 格全部一致 |
|
||||
| T4 回执版本 | 部分实现,整体验收未通过 | 默认与后端身份同步;minute正常版本探测失效旧cache、新Case成功回执/历史打开定向通过;旧block_scan缓存仍绕过版本检查,BUG-984另立补单 |
|
||||
| T5 记录、独立验收 | 本地记录与独立复核完成 | BUG-981~984、BLOCKED、CHANGELOG、测试清单与验收补单已记录;Python 广域 300 项/4 个基线失败,新增失败 0;T4/构建/部署缺口不写通过 |
|
||||
|
||||
所有报告保留已曝光数据边界,官方独立有效试次仍为 0;修复后数字是否变化以逐例复算为准,不能从实现改动推断数值必变。
|
||||
|
||||
## 红测与同窗对照证据
|
||||
|
||||
修复前输出(去掉所有案例参数,只保留测试标识):
|
||||
|
||||
```text
|
||||
FFF....F [100%]
|
||||
FAILED test_every_candidate_uses_own_date_and_caches_do_not_cross_dates[2000-01-01]
|
||||
FAILED test_every_candidate_uses_own_date_and_caches_do_not_cross_dates[2000-02-29]
|
||||
FAILED test_every_candidate_uses_own_date_and_caches_do_not_cross_dates[2000-12-31]
|
||||
FAILED test_real_cross_midnight_all_candidates_match_independent_dated_calculation
|
||||
4 failed, 4 passed in 7.32s
|
||||
```
|
||||
|
||||
日期为纯合成测试日期,不是案例出生资料。同日真实引擎 golden 修复前即绿。
|
||||
|
||||
性能与分数比较口径:公开已曝光 v3,raman / mean,半径 ±60、步长 1;20 个窗口各 121 候选。历史 12 文件打分身份 `b15d9ea15227cd58` 不变;新扩展生产身份 `7fffd1db612af1f2`。性能从原生静态上下文到矩阵及得分,5 对交替执行,不能与任务书另一环境的 8.6 秒直接比。
|
||||
|
||||
| 项 | 基线 | 修复后 |
|
||||
| --- | --- | --- |
|
||||
| 5 次耗时(秒) | 27.479 / 21.570 / 20.713 / 21.362 / 21.438 | 21.151 / 21.252 / 20.739 / 21.429 / 21.526 |
|
||||
| 耗时中位(秒) | 21.438497 | 21.252369(-0.8682%) |
|
||||
| 非跨日分数字节比较 | 19 个窗口,2299 候选 | 全部相同,矩阵字节亦同 |
|
||||
| 真实跨日窗口对日期正确独算 | 121 候选中 16 个跨日候选不同,同日 0 不同 | 全 rows / matrix 相同,差异 0 |
|
||||
| 该跨日窗口最大绝对分差 | 0.0267 | 0 |
|
||||
|
||||
这里是该公开样本的实测,不把算术上界或这个幅度推广到所有真实会话。可提交脱敏证据见 `docs/testing/rectification-cross-midnight-scoring-evidence-20260920.json`。
|
||||
|
||||
## 独立验收:明确未通过与另行问题
|
||||
|
||||
1. **BUG-984 / T4 未完整通过**:独立 TS 探针在无环境覆盖的 `block_scan` 历史缓存上实测 `cached:true`、旧算法 -7、HTTP 调用 0;真实工具路径写 started -8 / completed -7。SQL `max(engine_version)` 的源码核验显示聚合可能取 -8,不能据此证明重新评分。未真跑 SQL,因此数据库部分只报源码证据。补单 `TASK-rectification-cross-midnight-dasha-fix-20260920.md` 待批准,不擅改缓存政策/迁移。
|
||||
2. **BUG-982 / 既有聚类跨度**:纯虚构三分钟跨午夜簇沿 `build_candidate_decisions()` 输出 1440 分钟宽度;旧 BUG-624/639 的同日范围保护仍在,但不覆盖该跨日调用链。没有顺改候选淘汰或范围策略。
|
||||
3. **BUG-983 / 既有凌晨锚点**:前端凌晨申报的跨日钟点窗仍配原申报日期,生产枚举将起点绑当天、中心移到次日。helper 本轮只修与 `candidate_at` 一致,不能声称上游候选日期也已正确。
|
||||
|
||||
因此本轮可以分别验收“候选级日期修复”与“指定条件下版本身份”,不能说所有跨午夜路径端到端已闭环。BUG-981 未有部署证据前仍 investigating;BUG-982~984均 investigating,不冒标 resolved。
|
||||
|
||||
## 重新冻结与完整重跑
|
||||
|
||||
两份正式 freeze 均先于各自评分开始;评分结束再次核对真实当前文件身份。旧 8 份产物归档逐字节保留并有 manifest,原路径的两份旧 JSON 与旧 freeze 也未改;准备阶段冻结/试跑另标 superseded,不充当最终证据。
|
||||
|
||||
| 项目 | 结果 |
|
||||
| --- | --- |
|
||||
| 历史 12 文件打分身份 | `b15d9ea15227cd58`(不变) |
|
||||
| 新扩展生产 18 文件身份 | `7fffd1db612af1f2` |
|
||||
| 最终研究 7 文件身份 | `2931d4661bf53dde` |
|
||||
| 申报偏差重跑 | 900/900 组合完成、45 格、排除 0;旧新逐例所有保存字段 0 变化,耗时 399.902 秒 |
|
||||
| 固定口径 shadow 重跑 | 20/20 例完成、排除 0;逐例 0 变化,耗时 3.158 秒 |
|
||||
| T3 定向四文件 | 52/52 通过(包含 quick 桥接重复收集,不能算 52 个独立新增用例) |
|
||||
|
||||
数字未变不等于生产缺陷不存在:旧 T1 最终版已有离线按日期分组适配,新版矩阵走修复后的原生单调用;T2 的 shadow fact-ranker 本来按候选日期构事实,不走此次 helper。两者仍非完整生产问答/交付回放,也不是新的独立盲测。
|
||||
|
||||
独立只读审查已从真实文件复算 12/18/7 文件集及逐文件 SHA,核对历史 8 份归档与 Git 基线原字节、3 份 superseded 准备产物,以及两份正式冻结/报告/契约。900 组合完整、每格分母 20,summary 独立算术复算一致,Markdown 全部 45 格逐格吻合;20 例汇总与六项指标表亦同。独立审查另执行生产轻量 4 项、T3 选择性 5 项通过,未重复 900 评分;不把执行方的 52/52 冒称独立复跑。上表 399.902 秒为执行方外层耗时,JSON 内部 replay 区间为 399.819 秒,计时边界不同。
|
||||
|
||||
T2 数值口径:公开已曝光 v3、raman/mean、±10、步长 1、12文件打分身份 `b15d9ea15227cd58`,扩展生产上下文身份 `7fffd1db612af1f2`。竞争 top-1/top-3 0.45/0.50,哈希头名平均误差 6.45 分钟,三项仍未过原门槛;误确认 0、稀疏证据拒绝 1、确认覆盖 0;实际哈希头名命中 0.05。不得拿含并列 top-1 当唯一头名命中率,不因重新冻结增加官方盲测试次。
|
||||
|
||||
## 前端与确认门验收
|
||||
|
||||
基线测试工作树为已提交的 `932f2fff`;与开工 `03cba478` 之间只有两次任务文档提交,业务与测试代码相同。前端对照实际核对 1500 文件;没有安装/升级依赖或修改旧源码。以下最终轮覆盖报告路径更新,早期候选 77 失败只是阶段数据,不替代最终结果。
|
||||
|
||||
| 检查 | 基线 | 最终候选 |
|
||||
| --- | --- | --- |
|
||||
| TypeScript | 0 error | 0 error |
|
||||
| lint | 0 error / 120 warning | 0 error / 120 warning |
|
||||
| 全量前端 | 3486 总 / 3407 pass / 79 fail | 3493 总 / 3414 pass / 79 fail |
|
||||
| 新增版本与确认门定向 | — | 14/14 通过 |
|
||||
| BUG-621 + convergence + 新增版本 | 52 总 / 48 pass / 4 fail | 59 总 / 55 pass / 4 fail |
|
||||
| build | 外部 node_modules junction 超出 Turbopack filesystem root | 同原因失败;Static/gzip 未验收 |
|
||||
|
||||
全量 79 个失败标题与基线集合完全一致,新增失败 0;BUG-621 组合的 4 个失败标题也完全一致,为 Windows symlink EPERM。真实历史绑定 Skill 打开用例通过,但不是线上登录/DB E2E。Docker可用,部分全量失败涉及网络地址池/环境,不能写成无Docker。详见 `docs/testing/rectification-cross-midnight-frontend-results-20260920.json`。
|
||||
|
||||
主会话独立运行新增日期回归、桥接与隐私守卫共 80 项通过;17 个受保护文件(12冻结评分文件及确认门、历史枚举/请求实现、主API)与基线逐字节相同。实际 `holdout_passed()` 仍 False,runtime 六键值及类型全部相同。最终文档阶段再跑真实冻结身份、确认门及三组隐私守卫,86 passed / 0 failed(13.17 秒);14 份本轮 JSON 解析成功,`git diff --check` 通过。
|
||||
|
||||
## Python 广域回归收尾
|
||||
|
||||
基线三个校正 glob 共 284 项,280 passed / 4 failed。当前首轮共 300 项,294 passed / 6 failed;原四项失败标识及实际断言值均未改变,新增两项为版本身份相关断言:`test_score_candidates_matches_baseline_golden` 的决策代表候选 ID 不同,以及 `test_holdout_gate_keeps_proportional_default` 仍要求旧算法 -7。已保留该轮失败证据,不把它算作通过。真实引擎同进程旧/新身份 A/B 已确认仅两项身份变化,精确迁移后主会话核对所有其他 golden 叶与基线相同;未整份重写 golden、未改变分数或比较器。原进程出现的三个静态特征 hash 差异在另外两个新进程复测消失,旧身份独立复测与旧 golden 全字段相等,未覆盖这些历史 hash。修正后三文件定向(memoization、relative-support、freshness)25 passed / 0 failed(2.12 秒);两个 final.freeze 所绑定的 12/18/7 文件集合均不含这三项测试/快照文件,真实字节身份验证仍绿。主会话独立复跑上述 25 项亦全部通过(2.04 秒)。广域全套另起日志重跑,不覆盖首轮失败证据,最终 4 failed / 296 passed / 300 total(609.52 秒、exit 1);四个失败标识与实际断言值均同基线,新增失败 0,收集数增加 16(含桥接),但不宣称全套全绿。
|
||||
|
||||
| Python 广域失败项 | 基线与最终对照 |
|
||||
| --- | --- |
|
||||
| `test_long_real_conversation_reaches_vedastro_after_local_range_is_narrow` | 既有 winning_segment 不符,实际/期望字段值未变 |
|
||||
| `test_selector_changes_do_not_change_legacy_or_v5_score_bytes` | 既有 V5 分数 hash 不符,最终实际仍 `e20199f79f4283da`,未改断言 |
|
||||
| `test_v3_development_result_stays_shadow_only` | 两侧均 `v3_improved_case_count` 实际 1 / 期望 0 |
|
||||
| `test_frozen_implementation_hash_matches_manifest` | 既有历史 v2 hash 不符,最终实际仍 `f642651ef4dec9b5`,未刷新历史冻结 |
|
||||
|
||||
脱敏计数、失败标识与中间轮证据见 `docs/testing/rectification-cross-midnight-20260920-results.json`。本机 quick 仍因缺 mcp 阻断;前端 build / Static / gzip、受控登录态、数据库回执聚合与部署验收仍缺,按补验清单处理。
|
||||
|
||||
## 既有断言调整三栏
|
||||
|
||||
| 原值 / 原断言 | 新值 / 新断言 | 原因 |
|
||||
| --- | --- | --- |
|
||||
| 研究跨日测试要求原生生产 rows 不等于日期正确结果 | 要求原生 rows 等于独立日期正确结果,并锁定单矩阵调用 | 原断言描述旧缺陷;本单修复后新增正确性保障,不再锁住已知错误 |
|
||||
| 当前研究/确认测试引用旧 JSON / freeze | 引用新 cross_midnight JSON / final.freeze;旧文件保留字节验证 | 原报告留作历史,新实现重新预冻结;门禁值与独立性断言不变 |
|
||||
| 当前树身份只包含历史 12 文件 | 保留原断言,新增 18 文件生产与 7 文件研究身份及漂移拒绝 | 本次修复在 12 文件之外,不能靠旧hash没变宣称当前身份一致 |
|
||||
| 前端 currentTreeRerun 来源为旧同名 JSON | 新 `sealed_holdout_rerun_cross_midnight_2026_09_20.json` | 只迁来源;所有确认行为断言保留 |
|
||||
| relative-support 测试要求算法身份 `rectification-v5-matrix-scoring-7` | 要求 `rectification-v5-matrix-scoring-8` | 本单已授权同步算法身份;同一测试的 proportional 默认与 policy-v3 断言保留 |
|
||||
| memoization golden 代表候选 UUID `85ca5490-07ab-54b7-acf0-59385f705015`、snapshot 算法 -7 | 真实引擎输出 UUID `e8c11277-022c-519c-95e9-6a0a04e8bf23`、snapshot 算法 -8 | 版本身份参与确定性 UUID;同进程旧/新身份 A/B 仅这两叶变化。精确更新两叶,不整份刷新;主会话独立逐叶核对所有其他值与 Git 基线相同,数值、历史特征 hash、比较器均保留 |
|
||||
|
||||
## 报告保存与权限边界
|
||||
|
||||
原两份 JSON 的 shell 覆盖被拒后,没有换执行者覆盖它们;改用独占新建的正式报告 `reported_offset_cross_midnight_2026_09_20.json` 与 `sealed_holdout_rerun_cross_midnight_2026_09_20.json`。旧 JSON / 旧 freeze 原字节保留;准备阶段产物与最终身份分开,修改 evaluator 路径后重新冻结再重跑,不拿之前的冻结追认新脚本。当前契约与测试读取新正式路径,原数字留作历史,不因新实现自动判旧数字算错。
|
||||
@@ -291,7 +291,13 @@
|
||||
| `TASK-owner-case-purge-20260919.md` | `PROGRESS-owner-case-purge-20260919.md` | **上游库主案例与本机路径残留清除(只含本仓)**:镜像同步带进库主本人案例(敏感案例标识与本机路径)并被 `origin/staging` 命中,涉及无引用的 `versions/` 三快照、前端 fixture、Python 测试、整机扫描台账、会话转录及上游 SKILL 快照。运行时无特判不用动。产品拍板整体删除不留匿名版;fixture 统一虚构常量;`import_yinduzhanxing.py` 加隐私排除项 + 新增仓库级隐私守卫测试;上游 SKILL 快照等库主清完再重导入(BLOCKED 记录)。上游仓的清理指令另见 `UPSTREAM-INSTRUCTION-owner-case-purge-20260919.md`(交给库主,不在本仓执行)。BUG-972/973 | **已验收通过(2026-09-20,`497798ac`);未合入 staging,等产品放行** | 两轮:首轮未通过(1 个隐私守卫冲突:新增路径规则与答案键守卫冲突,该守卫在快速门 glob 内,合入会让门禁红)→ 修复单 `TASK-owner-case-purge-fix2-20260919.md` → `497798ac` 通过。Claude 在 Linux 全依赖环境独立复验:快速门 Python 步 859 passed / 0 failed(上一轮就是这步红),Python 全量 63 红与基线逐条相同、0 新红,收集数与删除清单已记录;tsc 0 / lint 0 error、120 warning 同基线 / `npm test` 失败清单为基线子集(少 1 条工作流 YAML,非回归)/ `○ /` Static、首屏 gzip 与基线字节相同(前端自首轮提交起零改动)。上游指令文件已逐字节还原为基线原文;12 个已删测试名与计数已落进度记录;BLOCKED 两条已划掉。校正 Skill 哈希包、注册表、上游快照、`frontend/src`、主 API 全程 0 改动;库主本机用户名 0 命中。遗留 P3:进度记录和 BUG 状态文字待后续对账修正 |
|
||||
| `TASK-consult-smalltalk-fastpath-20260920.md` | — | **普通对话寒暄轮快速通道**:真机一句「你好」触发完整窗口排盘(活动面板「已完成 4 步」)+ `## 先回答你的问题` + 400 字判词 + 扣 1 点。三层叠加:`index.ts` 两处「every turn 必调排盘」(BUG-922)与 `contractReady()` 的 `requireTool` 把排盘变成硬合同;`product-voice.ts` OPENER SHAPE 标「三种模式共用」;唯一的 chit-chat 豁免句只在 `natalSpokenReportContract` 里、只拼进本命 Agent(BUG-977)。计费侧「写回复」与「扣点」绑在 `complete_consultation_response` 同一次调用,`cancel` 只退款不写消息,所以今天没有「不扣点但保留对话」的通道。**产品拍板 a:不扣点、不排盘、回一句白话**;**分流不得用正则/关键词/长度阈值**,改为进 Agent 之前一次极短的结构化模型调用(复用本轮已选模型),fail-open 一律落回完整路径;BUG-922/923 的三处合同一个字不改;新增 `complete_consultation_free` 迁移。BUG-976/977 | 待领取 | — |
|
||||
| `TASK-rectification-validation-integrity-20260920.md` | `PROGRESS-rectification-validation-20260920.md` | **生时校正验证体系补缺(纯离线评测,不改打分不改产品)**:会议要求把「推断真实出生时间」与「用户认可的参考盘」分开证明。核对结论——**产品口径侧四条已落地**(`accepted`≠`confirmed` 两条写入路径、确认门 fail-closed 且 `holdout` 为 `not_ready` 使 `confirmation_allowed` 不可能为真、采用不写 `reported_birth_time`、无任何把采用率当准确率的指标;运行时也无按生日走捷径的分支);**缺口全在评测本身**。三条:① 封存契约 `rectification_sealed_holdout.v1.json` 的三个打分哈希互不相同(封存 `f41c298d` / 契约记录 `99730c84` / 基线实测 `b15d9ea1`),`official_eval_trial_count: 0`——当前实现**从未产出过一次有效官方盲测**,唯一跑过那次已被资料审计作废(top-1 `0.15`,发布门要 `0.60`),可见的 `0.45` 自带「不得当发布指标」标记(BUG-978);② 全部离线评测的候选窗**以真值为圆心**(`_candidate_moments()`、`request_from_case()` 的 `true_time`),生产以申报时间为圆心(`ENGINE_SEARCH_RADIUS_MINUTES = 15`)——「真值掉出窗外」这一失败模式从不可见(BUG-979);③ v3 封存但每例仅 3 事件、v4 有 7+ 事件却已被看过并用于调参,**无口径干净又贴近真实会话的封存集**;六题回放的 `0.80/0.55/0.35` 是「真值方向最优答」的上帝视角上界,±30/±60 仍低于发布门(BUG-980)。T1 申报偏差敏感性 sweep、T2 有效重跑 + 契约对齐 + **防复发新测试**、T3 只出 v5 采集协议、T4 记录。**硬红线:不得改 12 个打分文件、不得用封存集调参、不得把 `status` 改 `ready`。** 家庭信息(父母职业/兄弟姐妹)在拿到基线数字前不开工——现有七领域全是带日期事件,静态属性没有输入口。前置:owner-case-purge 三提交仍未合入 staging。BUG-978~980 | **已验收通过(2026-09-20,Claude 独立复算)**;独立盲测仍 blocked;门禁/部署待核验 | `932f2fff`。Claude 独立复核:T1 完整重跑 900 组合**逐例 8 字段 0 差异**、summary/specification 全等,另从 900 条逐例重算 45 格表与发布表逐位相同;T2 独立复跑 0.45/0.50/6.45/0/1.0/0.0 与哈希全序 0.05/0.10 全部一致;12 个打分文件字节未动、`status=not_ready`、`confirmation_coverage_rate=0`、实跑 `holdout_passed()`=False;新增/触及 Python 测试本机 38 条全绿;freshness 测试比对时排除 `frozen_at_utc`(BUG-693/694 教训已用上)。**执行方正确推翻任务书 T2.3**:「首次口径干净的官方盲测」与 BUG-428 防复发(已看过结果的案例不得再计入盲测)冲突,已核 BUG-428 原文,是任务书写错。环境缺口:本机 frontend 无 node_modules,tsc/lint/npm test/build 未能复核,采信执行方自报。遗留 → `TASK-rectification-cross-midnight-dasha-20260920.md`(BUG-981) |
|
||||
| `TASK-rectification-cross-midnight-dasha-20260920.md` | — | **跨午夜候选的 Dasha 边界错一天(生产打分)**:`scoring_service.py` 调 `merge_transition_proximity()` 只传**一个** `birth_date`,该函数用它算全部候选的 Vimshottari / Narayana 起始日期,候选之间只靠 `_context_time()` 的 `HH:MM` 区分、**日期被丢掉**。窗口跨午夜时午夜后候选的 dasha 边界整体错一天。Claude 验收时在生产调用链独立复现:窗口 `23:50→00:10`、21 个候选,**恰好那 11 个跨日候选分数错、10 个同日候选逐位相同**(幅度 +0.0267 / −0.0133,本例头名未变)。算术上界 = `cap/kernel_width`,day 精度 0.067 分/件,18 件可累计约 1.2 分,而随分钟变化项总量仅约 2.1 分 —— **上界是推的不是实测,真实幅度本单必须实测**。踩中路径:`late_night` 时段 `23:00–03:59`、`unknown` `00:00–23:59`、23:45 后或 00:15 前申报的 ±15 窗。连带发现:`calculation_spec()` 不含打分实现身份,修复后同一 spec hash 对应不同分数,历史 Case 静默失去可复现性(同 BUG-427 类型)。**产品 2026-09-20 已就三点拍板:A 修、B 修完重新冻结并重跑 T1/T2、C 让新旧结果可区分。** C 的做法经查证已修正:`calculation_spec_hash` 全在 **V4** 链路、**V9 零引用**,原提案 bump `INPUT_CONTRACT_VERSION` 对真实历史无效已作废;改为随修复 bump `engine_version`(`v9EngineVersion()` 缺省串,全仓只写不比、无相等性门控),**不得动 `skill_version`**(BUG-621:open RPC 要求绑定 Skill 等于当前版本,bump 会让历史校正打不开)。硬红线:只改「按候选日期取 dasha 起始」,不得动 kernel/cap/share 任一常数;确认门不变。BUG-981 | **待领取**(产品已放行) | — |
|
||||
| `TASK-rectification-cross-midnight-dasha-20260920.md` | `PROGRESS-rectification-cross-midnight-20260920.md` | **跨午夜候选的 Dasha 边界错一天(生产打分)**:`scoring_service.py` 调 `merge_transition_proximity()` 只传**一个** `birth_date`,该函数用它算全部候选的 Vimshottari / Narayana 起始日期,候选之间只靠 `_context_time()` 的 `HH:MM` 区分、**日期被丢掉**。窗口跨午夜时午夜后候选的 dasha 边界整体错一天。Claude 验收时在生产调用链独立复现:窗口 `23:50→00:10`、21 个候选,**恰好那 11 个跨日候选分数错、10 个同日候选逐位相同**(幅度 +0.0267 / −0.0133,本例头名未变)。算术上界 = `cap/kernel_width`,day 精度 0.067 分/件,18 件可累计约 1.2 分,而随分钟变化项总量仅约 2.1 分 —— **上界是推的不是实测,真实幅度本单必须实测**。踩中路径:`late_night` 时段 `23:00–03:59`、`unknown` `00:00–23:59`、23:45 后或 00:15 前申报的 ±15 窗。连带发现:`calculation_spec()` 不含打分实现身份,修复后同一 spec hash 对应不同分数,历史 Case 静默失去可复现性(同 BUG-427 类型)。**产品 2026-09-20 已就三点拍板:A 修、B 修完重新冻结并重跑 T1/T2、C 让新旧结果可区分。** C 的做法经查证已修正:`calculation_spec_hash` 全在 **V4** 链路、**V9 零引用**,原提案 bump `INPUT_CONTRACT_VERSION` 对真实历史无效已作废;改为随修复 bump `engine_version`(执行查证:默认串主要写 started/failed;成功回执及已有 minute 缓存门实际使用后端算法身份,故同步 `ALGORITHM_VERSION`,不新增历史打开门;旧“全仓只写不比”假设作废),**不得动 `skill_version`**(BUG-621:open RPC 要求绑定 Skill 等于当前版本,bump 会让历史校正打不开)。硬红线:只改「按候选日期取 dasha 起始」,不得动 kernel/cap/share 任一常数;确认门不变。BUG-981 | **已实现核心修复,整体验收未通过;独立分支交付供远程 review,不合入 staging** | 基线 `03cba478`;日期红绿、同日逐位、性能与900/20重跑完成;成功回执/缓存实际使用算法身份,已同步后端与前端标记,但独立审查发现BUG-984时段旧缓存与聚合来源未闭环,T4不能全通过。BUG-982/983另登记既有跨日缺口;补单与环境对照见进度。 |
|
||||
|
||||
### 跨午夜执行轮独立验收补单
|
||||
|
||||
| 任务书 | 状态 | 范围 |
|
||||
| --- | --- | --- |
|
||||
| `TASK-rectification-cross-midnight-dasha-fix-20260920.md` | 待产品确认后实施 | BUG-984:时段旧缓存不做算法身份失效、聚合回执可能取开始阶段新版而掩盖旧成功结果;原任务 T4 不判全通过。BUG-982/983 为另行登记的簇跨度与凌晨日期锚点问题,不在此补单顺改。 |
|
||||
|
||||
## 命名与归档
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# TASK · 跨午夜修复验收补单:缓存与结果身份(2026-09-20)
|
||||
|
||||
> 状态:待产品确认后实施;本文件仅记录验收未通过项,不代表批准扩大当前生产修复范围。原任务的候选级 Dasha 日期修复与评测继续完成,不能将本补单缺口冒写已通过。
|
||||
|
||||
## 0. 基线与串行依赖
|
||||
|
||||
- 原任务基线 `origin/staging = 03cba478`,前轮代码 `932f2fff`;待原任务最终提交后以其 SHA 为本单执行基线,不以未经确认的部署状态推导基线。
|
||||
- 依赖 `TASK-rectification-cross-midnight-dasha-20260920.md` 完成后串行执行。将涉及 `frontend/src/lib/rectification-agentic/v9/score-persist.ts`、回执查询及测试;不得与原任务 `engine-client.ts` 版本更新并行改同一文件。
|
||||
- 建议 worktree `.worktrees/rectification-cross-midnight-fix-20260920`,分支 `codex/rectification-cross-midnight-fix-20260920`。
|
||||
|
||||
## 1. 事故实证(按符号定位)
|
||||
|
||||
1. `scoreAndPersistV9Candidates()` 的 `block_scan` 分支先比较 `evidenceLedgerFingerprint`,命中即返回 `cached:true` 与缓存原 `algorithmVersion`;该返回发生在 `readV9EngineScoringIdentity()` 之前。跨午夜 late-night 时段可进入此分支,后端真实重算也确实会走本轮修复的 helper。故即使版本接口正常、后端已升级,旧时段分数仍可能被复用。
|
||||
2. `rectification-v9-tools.ts` 的 compare started 回执使用默认 engineVersion,成功回执使用实际 `persisted.algorithmVersion`。现有 `20260902020000_rectification_tool_activity_timing.sql` 的回执聚合用 `max(tr.engine_version)`,不是成功结果的身份。新版开始标记与旧缓存成功标记并存时,聚合可显示新版,不能证明新版重新算过。
|
||||
3. minute 分支已有算法身份相等缓存门,但 `readV9EngineScoringIdentity()` 可优先环境覆盖;仅有部分配置或版本接口失败时,不能保证实际旧缓存失效。不得把这些既有降级条件写成无条件安全。
|
||||
|
||||
## 2. 根因
|
||||
|
||||
- 时段与分钟评分缓存的身份条件不一致。
|
||||
- 聚合将运行阶段版本与计算结果来源版本混为同一可取字符串最大值的字段。
|
||||
- 任务书最初“全仓只写不比”的假设不成立;同步 bump 后端算法身份是必要但非充分条件。
|
||||
|
||||
## 3. 决策记录
|
||||
|
||||
产品原授权 C 要求新旧结果可区分,并禁止改 Skill 版本、V4 input contract 和新增历史打开相等门。本轮已同步既有后端算法身份和前端默认值,没有改缓存政策或数据库。
|
||||
|
||||
本补单建议:**所有评分缓存复用必须有实际计算身份;成功回执展示成功结果来源,不用开始阶段覆盖;无法取得可信当前身份时,不把旧缓存标为当前已验证结果。** 涉及版本接口失败时是否允许旧结果只读显示、是否新增向后兼容 SQL 迁移,需在本节由产品/架构明确后再实施,不能自行删历史结果或放宽门。
|
||||
|
||||
## 4. 硬红线
|
||||
|
||||
- 不重标旧结果为新算法,不删除历史回执/缓存来假装完成迁移。
|
||||
- 不 bump Skill,不改 V4 input contract,不引入按 engineVersion 拒绝打开历史会话。
|
||||
- 不调打分常数,不改确认门,不把已曝光重跑当独立盲测。
|
||||
- 如新增 SQL 迁移必须向后兼容当前已部署版本,真跑标准 DB 测试;不得原地改已应用迁移。
|
||||
- 不顺带修聚类跨度/凌晨日期锚点;它们分别为 BUG-982/983,需独立明确范围。
|
||||
|
||||
## 5. 任务分解与验收
|
||||
|
||||
### F1 · 先红测时段旧缓存
|
||||
|
||||
使用真实引擎脱敏 golden 构造旧算法时段缓存,同证据指纹、当前版本接口返回新身份。旧实现必须复现无网络重算仍返回旧结果;新实现不得把旧缓存作为当前分数复用。minute、block_scan 两条都覆盖,当前身份相同的正确缓存仍可命中。
|
||||
|
||||
### F2 · 成功回执身份
|
||||
|
||||
覆盖 started 新版本 / succeeded 旧缓存版本、diagnostics、失败重试与历史回执。用户看到的成功结果身份必须来自该成功结果,不能由字符串 `max` 决定。历史回执保持原值且旧会话仍可打开。若动 SQL,新增兼容迁移并真跑 `npm run test:db`。
|
||||
|
||||
### F3 · 失败与覆盖边界
|
||||
|
||||
分别测试无环境覆盖、完整覆盖、部分覆盖、版本接口超时/错误。按已批准策略说明何时重算、何时只读旧结果、何时拒绝复用;每种状态不得混淆当前身份与来源身份。
|
||||
|
||||
### F4 · 回归、记录与部署
|
||||
|
||||
前端 tsc/lint/相关与全量测试、build Static/gzip;数据库按需;BUG-621 历史打开回归必跑。更新 BUG-981 及缓存身份独立记录、BLOCKED、进度与测试清单。staging 受控会话分别验证 minute 与 late-night block_scan,不用匿名健康检查替代结果身份验收。
|
||||
|
||||
## 6. 让步顺序
|
||||
|
||||
先保证不伪造结果身份,其次保证缓存只复用兼容结果,再考虑缓存命中率;界面附加信息可延期,成功回执来源正确性不可砍。
|
||||
|
||||
## 7. 开工前置命令
|
||||
|
||||
先 `git status -sb`,再 fetch 并确认原任务最终 SHA;使用独立 worktree。读取 `AGENTS.md`、错误台账、前端三份规范、BUG-621/981 及本轮缓存身份记录;运行预检。未批准前不得执行迁移或推送生产。
|
||||
|
||||
## 8. BUG 编号
|
||||
|
||||
原日期修复为 BUG-981,附带既有范围/锚点问题为 BUG-982/983。本单缓存与聚合身份问题拟用 BUG-984;开工重核最大号与并行占用,按最终 Bug History 为准。
|
||||
Reference in New Issue
Block a user