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>
155 lines
18 KiB
Markdown
155 lines
18 KiB
Markdown
# 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。所有示例明确虚构,未使用用户账号或资料。
|