fix(rectification): enforce trusted result identity and preserve receipt provenance
Independent Staging Quality Gate / validate (push) Successful in 10m4s
Independent Staging Quality Gate / publish (push) Successful in 10m26s

Unify minute and block cache identity, keep unverifiable historical results read-only across server tools and write entrypoints, and aggregate completed receipt sources chronologically through a compatible function migration.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
jesse-ux
2026-09-20 18:03:38 +08:00
co-authored by Claude Code
parent 6dd62207eb
commit 8d0359fc62
37 changed files with 5983 additions and 95 deletions
@@ -2,7 +2,7 @@
## 结论与授权边界
**blocked:F2 方案 A 已完成局部实现,实测证实同一 turn 可出现不同身份的多个 completed,按补单须升级 B;未获 SQL 迁移授权,依指令停止进一步业务实施。F1 / F3 / F4 未完成,不可交付为 BUG-984 修复。**
**本地实现与自动化完成:F1/F2/F3 已实现,diagnostics追加修复后的新快照全量3588/3588、定向37/37、tsc/lint通过;标准DB40/40,首页Static、完整28资源gzip+0.040085%。主会话独立DB40/40、diagnostics最终定向40/40+tsc通过。未推送、未部署,受控真人验收仍缺口,BUG-984保持investigating。** 以下保留授权前记录,最新状态以文末「授权恢复」为准。
- 执行树:`.worktrees/rectification-cross-midnight-fix-20260920`,分支 `codex/rectification-cross-midnight-fix-20260920`
- 前置代码基线:`3f39bafc4a1fb7fc9d0a257d2528ea1a64295792`。主会话已成功推 staging 并核对 ls-remote**前轮 Gitea 写认证 blocker 已解除**;保留旧失败历史,不把它当本轮阻塞。
@@ -89,3 +89,66 @@
- 独立实跑身份文件 9 / 9 通过;BUG-621 历史打开与 case-service 两文件 29 / 29 通过;`tsc --noEmit` 退出 0;前置 Python 跨午夜 bridge 9 / 9 通过。混版本项只证明缺陷可达,未执行数据库聚合验收。
- 前置 Gitea run2819SHA `3f39bafc4a1fb7fc9d0a257d2528ea1a64295792`)的 validate 已 success,最后查询整轮仍 in_progress。staging `/login` 200、匿名 `/api/account` 401;健康响应的 web/API 部署均仍 `539d4daee4d0065f5ef3b974903ea8d639a249c6`,所以前置部署尚未确认完成。这些匿名检查不能代替缓存身份受控会话验收。
- 局部实现未推送;按任务书迁移授权停点报告,F1/F3/F4 保持 pending。
## 授权恢复与最终实现(2026-09-20)
产品明确回复继续并授权 B:只新增向后兼容函数体迁移、仅修回执聚合,不改表结构/已应用迁移/历史行,保留 owner/turn/attempt 与重试语义,真跑标准 test:db。恢复时 HEAD `6dd62207eb1ab04aaac8f6755146980b7abac8b2`。原停点是正确执行历史,不删除或改写。
主会话补报前置 run2819 completed/successstaging health 的 deployment.gitCommit 与 apiGitCommit 均等于 `3f39bafc4a1fb7fc9d0a257d2528ea1a64295792`。前置部署确认完成;本 agent 未访问线上,这不是本补丁受控身份验收。
### F1 / F2 / F3
- minute 与 block_scan 共用算法+策略完整 pair、证据指纹、范围/基线资料指纹;完整 env 保留明确覆盖语义,部分 env 补查 native pair、冲突 fail closed,不拿前端默认常量冒充部署覆盖。时段来源 policy/range 指纹只写新 JSON,不回填历史。
- 真实原生虚构输入 golden 经 `normalize_rectification_request``api_service.block_scan` 生成;旧 -7/当前 -8 minute 和 late-night 缓存均实跑应用链,旧重算、当前命中。F1 红测 11 项中 4 红(partial/unknown/旧block/当前block未探测),修后全绿。
- B 迁移 `20260920010000_rectification_receipt_result_identity.sql` 与旧函数除注释外仅身份 SELECT 不同:选中 successful attempt,否则 latest attempt;仅 completed 非空身份,started_at DESC、id DESC。真实 PostgreSQL 先红(8≠7)后绿,覆盖9/10、失败重试、同时间稳定排序、历史不重标与owner/turn/权限。
- 未知当前身份:旧结果只读、cached=false、来源不重标,不重算、不跑 oracle、不写 focus/inference/候选/验证;历史 GET/刷新、read-case、compare 同样显示「按旧算法产出」。新算响应与可信 pair 不同也保存真实来源并只读。
- 服务端写门覆盖 API direct accept、service accept/confirm、offer候选、选择/推断、block推进/拒绝、widen、tie-break、focus denial及闲置/出口修复。重查 dossier+当前身份,不信客户端flagstage/source交叉缺失、非最新resultId、无source具体采用一律拒绝,正常空Case收集不误拦。无生产引用的旧 session.ts helper未扩改。
- 独立review发现 stale 与 unknown 同锁composer会造成旧结果无法升级,已修:旧候选仍不可写,但可信当前pair已知时、非终止Case可点「重新比较」,复用既有message入口;未知身份不显示,不自动重算。测试覆盖历史投影→read-case提示compare→实际compare新来源,以及按钮handler的stale/unknown/terminal/busy派发边界。
- 独立review再发现 diagnostics 未经过身份门,原六种failure测试没有调用该工具。补调用后22项16绿/6红,证明未知身份仍请求了diagnostics;现入口在读取compute/诊断前短路:旧来源+notice/read_only、diagnostics=null、can_confirm_exact_minute=false、executed_methods=[],无source则engine_identity_unavailable。可信身份下仍独立诊断,新响应pair不匹配只读且不能确认,completed保持实际来源,9/10聚合用例保留;修后22/22。
- 不改Skill、input contract、评分/确认门、历史打开绑定,不删除或重标历史缓存;UI同步DESIGN,无Home状态增长。
### F4 证据与复跑环境
| 检查 | 已完成结果 |
| --- | --- |
| Linux基线全量(HEAD6dd62207应用代码) | 3575/3575fail/skip=0 |
| 身份及历史重算定向 | 22项;含minute/block、无/完整/部分env、冲突、接口异常/超时、来源缺失与滚动响应 |
| 最终四文件业务定向(加入stale测试之前) | 112/112 |
| Python日期+bridge+memoization | 32/32bridge重复收集已知,不称32个独立用例 |
| 标准 `npm run test:db` | 执行方40/40,主会话独立40/40304634ms),fail/skip=0,真实PostgreSQL17;独立日志 `<临时目录>/bug984-independent-db.log` |
| 中间完整修复轮 | 3587项,3586通过/1源码断言失败:终止提示改为historyReadonly,已附三栏同步 |
| 中间build | 首页 `┌ ○ /`25个首页直链JS/CSS gzip 655491→655584B+93B/+0.0142% |
| 保留的旧delivery全量 | 3588/3588fail/skip/cancelled=0307886ms;不替代追加diagnostics后的复跑 |
| 最终diagnostics全量 | 3588/3588fail/skip/cancelled=0259596ms;比基线3575增加13项 |
| 最终diagnostics build/gzip | `┌ ○ /` Static;完整28资源666078→666345B+267B/+0.040085%,在±2%内。读取index.html全部src/href的/_next/ JS/CSS,去query后去重,各文件gzipSync默认参数求和;旧25资源655491→655758B为遗漏3资源的局部统计,由本完整口径替代 |
| 最终diagnostics/按钮/身份/spoken定向 | 37/37;含22项身份、六种故障的diagnostics调用、实际handler派发与历史read→compare行为 |
| tsc/lint | 最终diagnostics后退出0lint 0 error/119 warning,不顺修warnings |
| BUG-621及最终独立补验 | 主会话先前43/43;身份+spoken(含按钮handler+BUG-621独立40/40、tsc退出0;日志 `<临时目录>/bug984-independent-final-targeted.log`diagnostics补丁后再次独立40/40且tsc0 |
| 隐私门 | 明确stage全部37个本单文件(含新增fixture/SQL)后 `python -m pytest tests/test_repo_privacy_markers.py`62/62;删除文档内两处HOME_PREFIX,日志以临时目录占位符保留 |
| 本轮部署/真人 | 未进行,BLOCKED与真人清单保留 |
Linux保真方式:`git archive HEAD` 保留真实symlink,增量文件在打包时替换;从不将Windows整个checkout覆到Linux。首轮基线3575/3571/4,失败为缺Git index/PyYAML/rsync;装备后3575全绿。源树`git ls-files -z`精确建立tracked index,临时repo无完整历史。基线目录带新增B迁移与原DB文件新增断言,但应用源码是HEAD;DB仍同一个test,应用基线总数不变。
- 保留 Docker runner `bug984-runner`node22-bookworm)、DinD `bug984-docker`、volume `bug984-validation`;无线上数据/凭据。
- 基线 `/repo/frontend`;中间 `/repo/bug984-fixed/frontend``/repo/bug984-final/frontend`;最终 `/repo/bug984-delivery/frontend`。这些是容器内路径,主会话复验不要用Windows主检出路径。
- diagnostics追加修复使用新快照 `/repo/bug984-diagnostics/frontend`,旧delivery与其证据不覆盖;最终30个修改/新增frontend文件在stage前与新快照逐文件SHA256相同(0差异),含SQL与DB测试;stage后diff-check发现新增SQL/golden的CRLF,已仅转为LF(内容/JSON/SQL语义不变),最终字节比较28相同、这2项去CRLF后相同。快照文档为创建时点;之后只补最终数字/独立证据,不影响源码测试。新增三文件也按明确清单加入临时tracked index。
- 标准复跑:`MSYS_NO_PATHCONV=1 docker exec -w /repo/bug984-diagnostics/frontend bug984-runner npm test`;同命令末尾换 `npm run test:db``npm run build``./node_modules/.bin/tsc --noEmit``npm run lint`。SQL和DB测试在diagnostics补丁中未改,沿用两方实际40/40,不伪称重复跑DB。
- 日志(volume内绝对路径):`/repo/baseline-equipped-tests.log``/repo/baseline-build.log``/repo/baseline-gzip.json``/repo/fixed-standard-db.log`(标准40/40);`/repo/fixed-tests.log``/repo/final-tests.log`(中间失败留存);旧delivery `/repo/delivery-tests.log``/repo/delivery-build.log``/repo/delivery-gzip.json`;最终 `/repo/diagnostics-tests.log``/repo/diagnostics-targeted.log``/repo/diagnostics-lint.log``/repo/diagnostics-build.log``/repo/diagnostics-gzip.json`
- 曾同步覆盖基线被权限系统拒绝,未重试覆盖,改为创建全新目录;首次final build抢在依赖copy完成前报next not found,等待copy完成再建成功。没有改业务/依赖声明来规避平台问题。
### 本轮既有断言/fixture调整(三栏)
| 原值 | 新值 | 原因 |
| --- | --- | --- |
| 部分policy env返回algorithm null、旧cache可用、0fetch | native完整pair、旧cache不可用、1fetch | 部分身份不能绕过算法核验;完整pair仍0额外fetch |
| 版本接口失败旧cache reusable=true | false并只读 | 策略b,保留显示不等于当前缓存命中 |
| 业务test-support无显式部署身份 | 与其fixture一致的rectification-v5/policy-v2完整env | 正常业务回归有受控可信身份,故障测试单独清env;不放宽生产 |
| block业务fixture algorithm=test、无policy | 与受控env一致的v5/policy-v2 | 不改blocks/分数/选择预期,仅补真实身份语义 |
| 两个业务score替身algorithm误用event-contract-v2 | rectification-v5event_contract_version保持原值 | 与test-support可信部署一致,不把滚动不一致误算正常业务 |
| 直接accept/confirm及collect替身没有dossier重读RPC | 补原candidate/dossier fixture | 新服务端写门必须重读,权限/确认/问题预期不变 |
| native policy滞后测试继承fixture env | 测试内清pair并恢复 | 必须真实走versions替身,不被完整env覆盖 |
| 无source采用返回candidate_not_found | RPC前result_identity_read_only | 提前拒绝不可核验具体结果,不能产生候选 |
| question/current_question/choice_card无只读分支,GET同步projection | 只读nullGET await可信projection | 历史直接刷新同样受保护,非删除断言 |
| 终止UI源码readonly && | historyReadonly && | 身份不可核验不等于Case已结束;不诱导强制新建 |
新增源形合同全部采用真实native golden;既有业务替身只是补身份或RPC,不声称为新合同golden。所有示例明确虚构,未使用用户账号或资料。
+1 -1
View File
@@ -293,7 +293,7 @@
| `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-978980 | **已验收通过(2026-09-20Claude 独立复算)**;独立盲测仍 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_modulestsc/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:0003:59`、`unknown` `00:0023: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()` 缺省串用于 started/failed;成功回执及 minute 缓存身份来自后端,旧「只写不比」假设作废),**不得动 `skill_version`**BUG-621open RPC 要求绑定 Skill 等于当前版本,bump 会让历史校正打不开)。硬红线:只改「按候选日期取 dasha 起始」,不得动 kernel/cap/share 任一常数;确认门不变。BUG-981 | **核心修复与 BUG-985 已 review 通过,本地合并 b27d4de9;推 staging 认证失败,端到端仍受 BUG-984 阻塞** | 实现 `aa46da10`(分支 `codex/rectification-cross-midnight-20260920`,未合入 staging)。Claude 独立 review:修复后整窗打分与**逐候选独立重算 21/21 一致**;非跨午夜分数基线 vs 修复**逐位不变**(我测半径 10 六例 + 半径 60 三例,执行方证据覆盖 19 例 / 2299 候选全部 `bytes_equal`);kernel/cap/share/`PRECISION_WEIGHTS` 一个未动;`status=not_ready`、coverage 0、`holdout_passed()` False、官方试次 0;决策 C 执行正确(`ALGORITHM_VERSION` 7→8`INPUT_CONTRACT_VERSION` 与 `skill_version` 未动,golden 里 `calculation_spec_hash` 不变可证);既有断言改动均带三栏说明且为加强。**P1 阻塞**:新增的 `test_same_day_public_aa_scores_keep_pre_fix_bytes` 写死 121 个浮点分数的 SHA-256,在 Claude 机器上 ordinal 2/3 红、**基线与修复分支同样红**(非修复所致),且经 `test_rectification_cross_midnight_gate.py` re-export 落入快速门 glob —— 同 glob 基线 214 passed/0 failed、`aa46da10` 4 failed,推 staging 会让门禁红。执行方自报未通过的 BUG-984 经独立确认成立且更重:`block_scan` 只比 evidence 指纹不读打分身份,而 `late_night`(299 min)/`unknown`(1439 min) 均 >120 走该分支、又恰是最易跨午夜的窗口 |
| `TASK-rectification-cross-midnight-gate-fix-20260920.md` | `PROGRESS-rectification-cross-midnight-gate-fix-20260920.md` | **review 修复单:门禁级浮点哈希断言(`aa46da10` 的合入阻塞项)**:新增回归把 121 个分数的 SHA-256 写死成字面量,于是断言范围把跨机 libm/pyswisseph 差异也圈了进去。实测该组 121 个分数**全无浮点尾噪**(`repr(s)==repr(round(s,4))` 121/121),所以差异是第 4 位真的不同,靠改序列化消不掉。同一提交刚改过的 `test_rectification_engine_memoization.py` docstring 正好写着「跨机舍入已漂 1.1e-3,不得整体 `==` 比较」——教训被引用了又被踩。执行方自己的证据 JSON 用的却是正确做法(`scores_bytes_equal` = 同机基线 vs 当前)。**根因**:要证的是相对不变量(同机基线 vs 当前),却实现成绝对不变量(当前 vs 某台机器的历史哈希)。F1 改用生产代码已有的 legacy 回退路径做同机 A/B 对照(去掉 `candidate_at` 即修复前行为),验收要求**两台浮点环境不同的机器各跑一次**、且回退核心修复后该测试仍绿(证明它守的是同日不变性而非跨午夜回归的替身);F2 bridge 重复收集(4 failed = 2×2);F3 查证 `block_scan` 重算是否经过被修 helper —— 会则 BUG-981 在 late_night/unknown 路径等于没上线、BUG-984 升为阻塞项;F4 记录。**硬红线:不得删测试/skip/把哈希改成本机当前值消红,不得改已验收的打分代码。** 串行:本单 → `aa46da10` 合入 → BUG-984 补单。BUG-985 | **已 review 通过;BUG-985 resolved;合入推送被 Gitea 认证阻塞,远端仍 a3577ce2** | 实现 `25232ce4`(分支 `codex/rectification-cross-midnight-gate-fix-20260920`)。F1 改为同进程 A/B:在 `scoring_service.merge_transition_proximity` 调用边界剥掉 `candidate_at` 走生产既有 legacy 回退,对比 121 个分数与整份贡献矩阵的 canonical 字节;另加 `legacy_calls == [121]` 与 `static_contexts is contexts` 两道防空转保险。Claude 复核:写死哈希字面量 **0 残留**;**第三套环境(Linux + Python 3.13,与执行方 Windows 3.11.7 不同)定向 18 条全绿** → 两机验收闭环;**回退日期修复探针:同日 3 条全绿、跨午夜相关 4 条转红**,证明同日不变性与跨午夜正确性已真正分开;快速门 glob staging `1b646659` 200 passed/0 failed → `25232ce4` 216 passed/0 failed+16,零新增失败,总数未降);相对合并点仅动 2 个测试文件 + 文档,`scripts/`、前端、golden、打分常数零改动。BUG-985 记录含我要求的防复发条,并正确认定为 BUG-733 同形复发。**建议 BUG-985 由 `blocked` 改 `resolved`**(证据即第三环境复跑)。环境缺口:完整快速门在 Claude 机器 120 秒超时被杀,6→4 那组数以执行方记录为准 |
| `TASK-rectification-cross-midnight-dasha-fix-20260920.md` | `PROGRESS-rectification-cross-midnight-fix-20260920.md` | **BUG-984 缓存与结果身份补单(BUG-981 的端到端阻塞项)**:`scoreAndPersistCurrentEvidence()` 的 `block_scan` 分支只比 `evidenceLedgerFingerprint` 即返回 `cached:true` 与旧 `algorithmVersion`,该返回发生在 `readV9EngineScoringIdentity()` **之前**`minute` 分支则有身份门。F3 已查证完整调用链到 `merge_transition_proximity()`,故核心修复合入后,**证据未变的历史跨午夜时段缓存命中仍返回修复前分数**——在本单闭环前不得声称跨午夜问题已修。边界已按源码收窄:`late_night`(23:0003:59) 跨日;`unknown`(00:0023:59) 虽 >120 分钟但**本身同日**,选中跨午夜子时段后才触发(此处修正了 Claude 先前把两者并列的说法)。产品 2026-09-20 放行且**同日拍板 F3 策略选 b**:版本接口取不到可信身份时,旧缓存**只读展示 + 显著标注「按旧算法产出」**,否决 a(重算,会把接口抖动放大成长等待,时段扫描受 `JYOTISH_HEAVY_COMPUTE_CONCURRENCY=2` 限流)与 c(照常复用,与已定原则冲突)。b 的三条边界:只读结果**服务端拒绝采用/确认**(靠删不靠藏,须有定向用例)、标注必须用户可见并对照 `VOICE.md`(涉界面同提交更新 `DESIGN.md`)、回执来源身份仍是产出它的版本。**F2 的 SQL 问题已查清并定序(A 先上 / B 兜底 / 第 10 版前必须解决)**:`engine_version` 一个字段被「部署声称的版本」(started/failed 行,取前端常量)与「实际产出结果的版本」(completed 行,命中旧缓存即旧版本)共用,聚合却用与版本先后无关的字符串 `max`。**该缺陷此前一直撞对,`aa46da10` 之后才变真错**:它把 `v9EngineVersion()` 缺省由 `rectification-v5` 改为 `…scoring-8`,started 行遂在字符串序上反超 completed 行 → 回执显示第 8 版而分数来自第 7 版缓存;已核 `deploy/`、`.gitea/` 未设 `RECTIFICATION_ENGINE_VERSION`,走缺省,**是真实行为**。第二个缺陷:实跑 `max("…-10","…-9") = "…-9"`,**该聚合在第 10 版静默反向**(现为第 8 版)。Astarted/failed 不再写版本(应用层,必做);A 的漏洞(同 turn 多个 completed 行版本不同)**必须实测取证,不得以「应该不会」结案**;B=聚合改取成功结果那一行(只改函数体,向后兼容);C=拆列本单不做。**四项全部可开工。**硬红线:不重标/不删历史结果,不 bump Skill,不改 V4 input contract,不引入按 `engineVersion` 拒绝打开历史会话。串行:BUG-985 合入 → 本单。BUG-984 | **blockedF2 A 局部完成,多 completed 混版本实测成立,等待 B 的 SQL 授权;F1/F3/F4 pending** | `codex/rectification-cross-midnight-fix-20260920`;前置认证已解除,代码基线 `3f39bafc`、文档基线 `f09f3d80`;本轮未推送 |
| `TASK-rectification-cross-midnight-dasha-fix-20260920.md` | `PROGRESS-rectification-cross-midnight-fix-20260920.md` | **BUG-984 缓存与结果身份补单(BUG-981 的端到端阻塞项)**:`scoreAndPersistCurrentEvidence()` 的 `block_scan` 分支只比 `evidenceLedgerFingerprint` 即返回 `cached:true` 与旧 `algorithmVersion`,该返回发生在 `readV9EngineScoringIdentity()` **之前**`minute` 分支则有身份门。F3 已查证完整调用链到 `merge_transition_proximity()`,故核心修复合入后,**证据未变的历史跨午夜时段缓存命中仍返回修复前分数**——在本单闭环前不得声称跨午夜问题已修。边界已按源码收窄:`late_night`(23:0003:59) 跨日;`unknown`(00:0023:59) 虽 >120 分钟但**本身同日**,选中跨午夜子时段后才触发(此处修正了 Claude 先前把两者并列的说法)。产品 2026-09-20 放行且**同日拍板 F3 策略选 b**:版本接口取不到可信身份时,旧缓存**只读展示 + 显著标注「按旧算法产出」**,否决 a(重算,会把接口抖动放大成长等待,时段扫描受 `JYOTISH_HEAVY_COMPUTE_CONCURRENCY=2` 限流)与 c(照常复用,与已定原则冲突)。b 的三条边界:只读结果**服务端拒绝采用/确认**(靠删不靠藏,须有定向用例)、标注必须用户可见并对照 `VOICE.md`(涉界面同提交更新 `DESIGN.md`)、回执来源身份仍是产出它的版本。**F2 的 SQL 问题已查清并定序(A 先上 / B 兜底 / 第 10 版前必须解决)**:`engine_version` 一个字段被「部署声称的版本」(started/failed 行,取前端常量)与「实际产出结果的版本」(completed 行,命中旧缓存即旧版本)共用,聚合却用与版本先后无关的字符串 `max`。**该缺陷此前一直撞对,`aa46da10` 之后才变真错**:它把 `v9EngineVersion()` 缺省由 `rectification-v5` 改为 `…scoring-8`,started 行遂在字符串序上反超 completed 行 → 回执显示第 8 版而分数来自第 7 版缓存;已核 `deploy/`、`.gitea/` 未设 `RECTIFICATION_ENGINE_VERSION`,走缺省,**是真实行为**。第二个缺陷:实跑 `max("…-10","…-9") = "…-9"`,**该聚合在第 10 版静默反向**(现为第 8 版)。Astarted/failed 不再写版本(应用层,必做);A 的漏洞(同 turn 多个 completed 行版本不同)**必须实测取证,不得以「应该不会」结案**;B=聚合改取成功结果那一行(只改函数体,向后兼容);C=拆列本单不做。**四项全部可开工。**硬红线:不重标/不删历史结果,不 bump Skill,不改 V4 input contract,不引入按 `engineVersion` 拒绝打开历史会话。串行:BUG-985 合入 → 本单。BUG-984 | **本地完成:diagnostics追加修复后全量3575→3588全绿,标准DB40/40Static/完整28资源gzip+0.040085%tsc/lint通过;主会话独立DB40与最终定向40全绿。未推送,真人/部署待主会话** | `codex/rectification-cross-midnight-fix-20260920`;前置认证已解除,代码基线 `3f39bafc`、文档基线 `f09f3d80`;本轮未推送 |
## 命名与归档