Files
Jyotisha/docs/tasks/PROGRESS-rectification-cross-midnight-fix-20260920.md
T
jesse-uxandClaude Code 8d0359fc62
Independent Staging Quality Gate / validate (push) Successful in 10m4s
Independent Staging Quality Gate / publish (push) Successful in 10m26s
fix(rectification): enforce trusted result identity and preserve receipt provenance
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>
2026-09-20 18:03:38 +08:00

18 KiB
Raw Blame History

BUG-984 缓存与成功结果身份补单进度(2026-09-20)

结论与授权边界

本地实现与自动化完成: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 已解除;保留旧失败历史,不把它当本轮阻塞。
  • 本轮 fetch 发现补充文档 f09f3d809a538a48979b94f1c851d1dc528e49ba,干净树快进到该提交。它仅修改任务书与索引,代码仍为上述基线。
  • 已读 AGENTS、前端三规范、BUG-621/981/984 完整记录与错误台账。最大 Bug 编号 985,本轮续写 BUG-984,不占新号。
  • 不 push、不调用线上、不读取凭据、不改 workflow/main/DNS/SQL/Skill/input contract/评分常数/确认门,不删除或重标历史缓存。

F2 实测与应用层可行性

A 的局部实现

createRectificationV9Tools() 的 compare / diagnostics started 与 failReceipt 不再携带部署声称版本;completed 只记录实际返回的 algorithmVersion,compare 缺失时不回退前端默认版本。

同一真实 golden 用例先红后绿:原实现 started 仍写 -8,修改断言后 6 pass / 1 fail;局部修复并补两条测试后 9 pass / 0 fail。

已构造出的 B 触发条件

frontend/tests/rectification-engine-version-cross-midnight.test.ts 的 runGoldenToolSequence() 通过实际 createRectificationV9Tools() 构造一个 Case/turn,依次运行 compare、diagnostics;RPC/fetch 为受控替身,响应结构和数值来自既有原生引擎虚构输入 golden,仅算法身份标签被替换以模拟滚动版本。未声称执行未来 -9/-10 算法。

行 实际工具 状态 写入身份
1 compare started null
2 compare completed scoring-9
3 diagnostics started null
4 diagnostics completed scoring-10

两条 completed 的 turn_id 相同;最新成功来自 scoring-10,但字符串最大值是 scoring-9。测试保留的是缺陷诊断证据,不是“聚合已修”的验收绿灯。并未运行真实 PostgreSQL 聚合,因此不宣称数据库端到端已验证。

  • compare 与 diagnostics 各自独立调用引擎;两次完成之间没有“同 turn 必须同算法”的锁或一致性检查。部署滚动/环境来源差异不会被 A 消除。
  • 现有 get_agentic_rectification_turn_receipt() SQL 按 selected successful attempt 过滤后仍执行 max(tr.engine_version),活动只返回 tool/status/methods/timing/fingerprint,不含各 completed 的 engine_version。
  • loadV9TurnReceipt() 只能读这个聚合字段;既有历史 compare fingerprint 仅含 hash/timings,diagnostics fingerprint 仅为 hash。因此应用层拿既有 RPC 输出无法无损恢复各历史成功行身份,也不能把当前 dossier 最新结果冒充历史 turn 来源。
  • 在新 fingerprint 塞身份只能处理新数据,修不了历史 max 污染;引入第二条服务角色原始表读取会另造回执权限/attempt/重试排序投影,不是本单 A,且任务书已明确“构造成立就升 B”。因此不绕过授权另造旁路。
  • 建议下一步 B:新增向后兼容函数体迁移,保留 owner/turn/attempt 过滤,仅从实际成功行取身份;明确多工具/失败重试语义,使用 started_at 与 id 稳定排序,不依赖字符串版本序。不得原地改已应用迁移。产品负责人明确授权迁移后再实施并真跑 test:db;主会话审查不代替该授权。

任务状态

项 状态 剩余工作
F1 minute / block_scan 缓存 pending 真实 golden 时段旧缓存红测、统一可信身份复用条件;当前完全未改
F2 成功回执 blocked A 局部完成;多 completed 实证触发 B,等待迁移授权
F3 策略 b pending 只读标注及所有服务端写入口拒绝尚未实现,不是只藏按钮
F4 完整回归/交付 pending 全量、build Static/gzip、DB 与受控 staging minute/late-night 验收未完成

已执行检查

检查 结果
pre_work_check(Python 3.11.7) remote verified;focused 23 pass / 1 fail,历史 .workbuddy 镜像路径断言;与台账已知症状一致,未造目录
工具能力 Node 22.23.2;Docker daemon 29.8.0 可用;node:22-bookworm / postgres:17-alpine 已有
算法身份文件基线 7 / 7 pass
A 红测 6 pass / 1 fail,started 身份断言
A + 多成功来源诊断 9 / 9 pass;含缺陷存在证明,不是 F2 总体验收通过
tsc --noEmit 0 error
定向五文件(含 BUG-621、case-service、skill-registry、activity) 61 tests / 57 pass / 4 fail;四项均 Windows symlink EPERM,详见下列名单;尚未另跑基线逐条对照,不标全绿
lint 0 error / 120 warnings;未顺手修改既有 warnings
全量 / build / Static / gzip / 标准 DB 因必须 B 的授权停点而暂缓,未执行;不是预设工具缺失

定向四项失败来自未改动的 skill-registry.test.ts,单文件复跑 16 tests / 12 pass / 4 fail,失败标题精确如下:

  1. checked-in registry verifies hashed product packages and leaves consult on the live skill
  2. path traversal and symlink escape fail closed
  3. symbolic links are rejected even when their target stays inside the project root
  4. live consult skill reads a hand-updated tree without a registry hash

没有以修改业务代码或弱化安全断言消红。DESIGN 未修改:本轮在 F2 授权停点终止,尚未实施任何 UI 标注/形状变化;后续 F3 必须同提交更新 DESIGN。

断言调整说明

原值 新值 原因
新 Case compare/diagnostics started 回执身份为 CURRENT started 为 null,completed 保持真实 CURRENT F2 A 的明确授权;开始阶段未产生结果,不能冒充成功来源

新增两条:diagnostics 503 的 failed 身份为空;同 turn 两工具 completed -9/-10 与字符串最大值相冲突。未知身份的既有缓存降级测试仍如实锁现状,F3 未开始,不声称已修。

部署与后续独立验收

本 agent 无线上访问。主会话通知前置 run2819 validate 已 success、publish 尚 in_progress,最近通知的 staging health 仍为旧 SHA;这不构成本轮部署或身份验收证据。

独立验收重点:工具 started/failed 实参、完成态来源无默认回退、混版本诊断测试的边界、旧回执按绑定 Skill 打开不变。F1/F3 的实现与完整测试须在解除 B 授权阻塞后继续。真人清单:docs/testing/rectification-cross-midnight-fix-20260920.md。

主会话独立复核(2026-09-20)

  • 审查本地实现提交 d575e89a:仅修改工具身份写入与定向测试,未改 SQL、缓存、UI 或评分。核对最新定义仍为 20260902020000_rectification_tool_activity_timing.sql:活动输出未含各成功行版本,140–146 行仍跨阶段做 max(engine_version)。认可 A 的局部修复及触发 B 的诊断结论,不将本轮标为完整验收通过。
  • 独立实跑身份文件 9 / 9 通过;BUG-621 历史打开与 case-service 两文件 29 / 29 通过;tsc --noEmit 退出 0;前置 Python 跨午夜 bridge 9 / 9 通过。混版本项只证明缺陷可达,未执行数据库聚合验收。
  • 前置 Gitea run2819(SHA 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/success,staging 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+当前身份,不信客户端flag;stage/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/3575,fail/skip=0
身份及历史重算定向 22项;含minute/block、无/完整/部分env、冲突、接口异常/超时、来源缺失与滚动响应
最终四文件业务定向(加入stale测试之前) 112/112
Python日期+bridge+memoization 32/32;bridge重复收集已知,不称32个独立用例
标准 npm run test:db 执行方40/40,主会话独立40/40(304634ms),fail/skip=0,真实PostgreSQL17;独立日志 <临时目录>/bug984-independent-db.log
中间完整修复轮 3587项,3586通过/1源码断言失败:终止提示改为historyReadonly,已附三栏同步
中间build 首页 ┌ ○ /;25个首页直链JS/CSS gzip 655491→655584B,+93B/+0.0142%
保留的旧delivery全量 3588/3588,fail/skip/cancelled=0,307886ms;不替代追加diagnostics后的复跑
最终diagnostics全量 3588/3588,fail/skip/cancelled=0,259596ms;比基线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后退出0;lint 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-v5,event_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 只读null,GET await可信projection 历史直接刷新同样受保护,非删除断言
终止UI源码readonly && historyReadonly && 身份不可核验不等于Case已结束;不诱导强制新建

新增源形合同全部采用真实native golden;既有业务替身只是补身份或RPC,不声称为新合同golden。所有示例明确虚构,未使用用户账号或资料。