Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ designs/
.playwright-mcp
# Claude Code 的 agent 工作区,由工具自行管理
.claude/worktrees/


.pi
57 changes: 57 additions & 0 deletions output/boss-chat-tab-timeout-delivery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Delivery

状态:Partial
- 步骤 review 最新一轮评审仍有 blocking:[qa-engineer] Bugfix 缺少修复前红灯证据:`output/boss-chat-tab-timeout-fix.md:13-18` 只描述修复后的行为测试,共享黑板也只记录修复后 `reply_unread` 测试 9 passed、0 failed;没有真实命令输出证明其中至少一个回归用例在旧的无条件导航实现上失败。按 bugfix 红→绿要求,现有证据不足以支撑可合并,需要保留旧实现或修复前提交上的同一目标测试失败输出,以及当前实现上的通过输出。
- 步骤 review 最新一轮评审仍有 blocking:[qa-engineer] 关键错误分支“首次等待失败后,恢复导航本身失败”没有行为测试覆盖。实现位于 `src-tauri/src/rpa/boss/handler/reply_unread.rs:218-221`,但现有四个编排测试 `src-tauri/src/rpa/boss/handler/reply_unread.rs:743-785` 只覆盖就绪复用、首次等待成功、恢复等待成功和两次等待超时;没有给 `navigate_results` 注入恢复导航错误并断言恰好两次导航、仅一次等待,以及错误同时保留首次等待和恢复导航上下文。这是已批准诊断合同 `output/boss-chat-tab-timeout-diagnosis.md:28-30` 所要求的最终失败上下文路径,属于关键失败路径测试断裂。
- 步骤 review 最新一轮评审仍有 blocking:[devops-engineer] 缺少真实 BOSS 运行环境中的启动与行为响应证据,现有证据只能证明编排单元测试和静态检查通过,不能证明周期任务在标签超时场景下已恢复稳定运行,因此不足以支撑本修复为 release-ready。`output/boss-chat-tab-timeout-fix.md:28` 明确承认线上页面与风控响应无法由本地单元测试完整复现;至少需要核对修复版本的运行日志,证明就绪页被复用、首次失败时仅恢复一次,并且后续能够进入未读列表处理或明确终止。
- 步骤 review 最新一轮评审仍有 blocking:[devops-engineer] `output/boss-chat-tab-timeout-fix.md:3-8,28` 将重复冷导航直接定性为“根因”和“已确认”,但文档同时承认没有真实线上复现;当前日志只能支持该因素与故障相符,尚不能排除登录状态、风控页面、标签 DOM 陈旧或接口加载异常。该完成措辞超出现有证据,存在发布结论失真的风险。

## 交付范围
- 目标:定位 BOSS 周期间歇自动回复反复等待会话分类标签超时的根因,实施稳健修复并验证
- 路由:class=quick_edit · kind=light · depth=fast
- 计划 boss-chat-tab-timeout:3/3 done · 0 blocked · 0 未结算
- [done] diagnose 追踪沟通页面导航、分类标签等待与周期重试链路,形成根因诊断(backend-engineer,验收 source-present)
- [done] fix 修复分类标签就绪判定与异常恢复逻辑并补充回归测试(backend-engineer,验收 build-test)
- [done] review 评审故障修复的正确性、回归风险与可观测性(qa-engineer,验收 review-clean)

## 关键文件
- src-tauri/src/rpa/boss/handler/chat_list.rs(主会话声明的改动)
- src-tauri/src/rpa/boss/handler/reply_unread.rs(主会话声明的改动)
- output/boss-chat-tab-timeout-diagnosis.md(主会话声明的改动)
- output/boss-chat-tab-timeout-fix.md(主会话声明的改动)
- output/boss-chat-tab-timeout-review.md(主会话声明的改动)
- output/boss-chat-tab-timeout-delivery.md(主会话声明的改动)

## 验证
- [diagnose] source-present → pass
- [fix] source-present → pass
- [fix] `pnpm run build` → pass exit=0
- [fix] `pnpm run test` → pass exit=0
- [fix] lint → skipped
- [fix] typecheck → skipped
- [review] review-clean → skipped
- 合同:N/A —— 本次改动不涉及前后端接口合同
- 治理/安全:review:安全席无 blocking(仅评审意见,未替代自动化扫描)
- 运行:not verified —— 未启动服务做真实运行探测
- 部署:not deployed —— 未获部署授权,也未执行任何部署动作

## 未完成或风险
- 步骤 review 最新一轮评审仍有 blocking:[qa-engineer] Bugfix 缺少修复前红灯证据:`output/boss-chat-tab-timeout-fix.md:13-18` 只描述修复后的行为测试,共享黑板也只记录修复后 `reply_unread` 测试 9 passed、0 failed;没有真实命令输出证明其中至少一个回归用例在旧的无条件导航实现上失败。按 bugfix 红→绿要求,现有证据不足以支撑可合并,需要保留旧实现或修复前提交上的同一目标测试失败输出,以及当前实现上的通过输出。
- 步骤 review 最新一轮评审仍有 blocking:[qa-engineer] 关键错误分支“首次等待失败后,恢复导航本身失败”没有行为测试覆盖。实现位于 `src-tauri/src/rpa/boss/handler/reply_unread.rs:218-221`,但现有四个编排测试 `src-tauri/src/rpa/boss/handler/reply_unread.rs:743-785` 只覆盖就绪复用、首次等待成功、恢复等待成功和两次等待超时;没有给 `navigate_results` 注入恢复导航错误并断言恰好两次导航、仅一次等待,以及错误同时保留首次等待和恢复导航上下文。这是已批准诊断合同 `output/boss-chat-tab-timeout-diagnosis.md:28-30` 所要求的最终失败上下文路径,属于关键失败路径测试断裂。
- 步骤 review 最新一轮评审仍有 blocking:[devops-engineer] 缺少真实 BOSS 运行环境中的启动与行为响应证据,现有证据只能证明编排单元测试和静态检查通过,不能证明周期任务在标签超时场景下已恢复稳定运行,因此不足以支撑本修复为 release-ready。`output/boss-chat-tab-timeout-fix.md:28` 明确承认线上页面与风控响应无法由本地单元测试完整复现;至少需要核对修复版本的运行日志,证明就绪页被复用、首次失败时仅恢复一次,并且后续能够进入未读列表处理或明确终止。
- 步骤 review 最新一轮评审仍有 blocking:[devops-engineer] `output/boss-chat-tab-timeout-fix.md:3-8,28` 将重复冷导航直接定性为“根因”和“已确认”,但文档同时承认没有真实线上复现;当前日志只能支持该因素与故障相符,尚不能排除登录状态、风控页面、标签 DOM 陈旧或接口加载异常。该完成措辞超出现有证据,存在发布结论失真的风险。
- 未验证:fix / lint:skipped —— 未探测到该项目的对应命令,也没有在 .pi/dev/config.json 中配置
- 未验证:fix / typecheck:skipped —— 未探测到该项目的对应命令,也没有在 .pi/dev/config.json 中配置
- 未验证:review / review-clean:skipped —— 只读评审由 dev_review 调度,不在机械验收中判定

## 证据
- `.pi/dev/plan.json`:计划 DAG 与每步状态(可恢复)
- `.pi/dev/route.json`:本次路由定级与理由
- `.pi/dev/ledger.jsonl`:append-only 审计账本(路由 / 验收 / 评审 / 确认门 / 交付)
- 验收报告 4 份,最近一次 review @ 2026-08-21T07:58:33.203Z
- `.pi/dev/evidence/`:命令完整输出(报告中的 output 已截断)
- 评审报告 1 份,含各席位 accepts / blocking / advisory / evidence 原文
- `.pi/dev/blackboard.md`:当前黑板(合同、实际状态、finding、待确认项)

## 恢复/继续
- 计划已全部结算;继续新目标请先调用 dev_route 重新定级,不要沿用本次路由
34 changes: 34 additions & 0 deletions output/boss-chat-tab-timeout-diagnosis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# BOSS 周期间歇自动回复超时诊断

## 结论

反复失败不是模型回复、未读列表切换或登录必然失效,而是**长驻周期任务复用同一个 owned tab,却在每一轮回复开始时都对当前沟通页再次执行 `page.get(BOSS_CHAT_URL)`,制造了不必要的整页冷导航**。BOSS 沟通页冷加载不稳定时,页面在 20 秒内没有重新挂载 `.label-list li .label-name`,于是 `wait_for_chat_page` 抛出日志中的固定错误。

## 证据链

1. 日志错误文本只可能来自 `src-tauri/src/rpa/boss/handler/chat_list.rs:53-54`:等待 `.label-list li .label-name` 超时。
2. `src-tauri/src/rpa/boss/handler/reply_unread.rs:50-52` 每轮均先记录“正在打开沟通页面”,随后无条件调用 `page.get(BOSS_CHAT_URL)`,再等待分类标签。
3. 该运行是 managed 周期投递任务。`src-tauri/src/rpa/run_flow.rs` 中 `PeriodicTarget::OwnedTab` 会让同步历史、自动回复和投递长期共用任务的 `main_tab`;`idle_until` 每个轮询周期都会再次调用 `run_reply_round`。因此这里不是一次性新标签页,无条件 `get` 会每隔数分钟重复刷新同一页面。
4. 12:06 历史同步刚在相同 tab 完成,12:06:53 自动回复又重新打开沟通页并成功;从 12:12 起连续刷新后大量超时,但 13:11、13:20 又能成功并打印“没有未读消息”。间歇成功证明:
- 选择器并非永久失效;
- 登录并非持续失效;
- 故障符合重复冷导航触发的页面加载/接口/风控抖动,而不是业务判断失败。
5. 每次失败约发生在“正在打开沟通页面”后 20 多秒,与 `wait_for_chat_page(..., 20s)` 完全吻合;错误发生在任何未读列表逻辑之前。

## 根因与放大因素

- **直接根因**:复用 tab 的轮询路径缺少“当前沟通页已经就绪则直接复用”的快速路径。
- **放大因素**:就绪失败后没有一次受控恢复,也不记录当前 URL/页面状态;所有失败都被笼统描述为“可能未登录或未加载完成”,导致调度器每隔数分钟以同样方式整页重载并重复失败。
- **不是根因**:“会话没有可恢复的求职方案归属”只影响采用哪个回复配置;它发生在成功读取会话之后,与分类标签加载超时无关。

## 修复合同

1. 打开沟通页前先探测分类标签:已有标签时复用当前 DOM,不执行导航。
2. 标签不存在时才导航;导航后等待标签。
3. 首次导航等待失败时执行一次受控恢复(重新导航并等待),避免瞬时空白/未挂载直接判整轮失败;禁止无限重试。
4. 最终失败信息应保留首次与恢复失败上下文,便于区分持续登录失效和偶发加载失败。
5. 把“是否需要导航/是否恢复”的状态决策抽成可单元测试的纯逻辑,覆盖:已就绪、首次成功、首次失败后恢复成功、两次均失败。

## 风险边界

本地无法完整复现线上 BOSS 页面和风控响应,因此不能证明所有页面异常都消失。修复目标是去掉确定存在的重复冷加载,并为一次瞬时失败提供有界恢复;若恢复后仍无标签,应继续返回错误而不是把页面误判成“没有未读”。
27 changes: 27 additions & 0 deletions output/boss-chat-tab-timeout-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# BOSS 周期间歇自动回复超时修复

## 高概率诱因(待真实环境确认)

周期任务长期复用 owned tab,但此前每轮自动回复都会无条件 `page.get(BOSS_CHAT_URL)`。这会把已经可用的沟通页反复变成冷加载;BOSS 页面偶发未在 20 秒内重新挂载分类标签时,整轮便以“等待会话分类标签超时”失败。

日志中偶尔成功打印“没有未读消息”,说明标签选择器并非永久失效、登录也并非持续失效,故障与重复冷导航引起的间歇性加载失败高度吻合,但现有证据不能排除短时登录态、风控页、陈旧 DOM 或接口异常。

## 实际修复

- `src-tauri/src/rpa/boss/handler/chat_list.rs`
- 增加分类标签存在性探测 `is_chat_page_ready`。
- `src-tauri/src/rpa/boss/handler/reply_unread.rs`
- 用 `ensure_chat_page` 替代每轮无条件导航,并以可替换的 `ChatPageDriver` 隔离浏览器副作用。
- 当前 DOM 已有分类标签时直接复用页面。
- 标签不存在才导航;首次等待失败后只执行一次恢复导航,禁止无限重试。
- 最终错误同时保留首次等待及恢复导航/等待上下文。
- 行为级回归测试直接驱动同一编排函数,断言:已就绪时 0 次导航、首次成功 1 次导航、恢复成功恰好 2 次导航、恢复导航失败保留两段上下文、两次超时后终止且错误包含两段上下文。

## 行为边界

- 正常就绪页面不再被周期性刷新。
- 非沟通页或未就绪页仍会导航至 BOSS 沟通页。
- 一次瞬时冷加载失败有一次恢复机会。
- 两次均失败仍返回错误,不会误报成“没有未读消息”。
- 线上页面与风控响应无法由本地单元测试完整复现;本修复消除代码中确定存在的每轮无条件冷加载,并增强有界恢复与诊断信息,但线上故障是否消失仍需修复版本运行日志确认。
- 修复前没有保留同一行为测试的红灯命令输出;原始运行日志与旧代码中的无条件 `page.get` 是故障证据,但不等价于严格的测试红灯记录。
29 changes: 29 additions & 0 deletions output/boss-chat-tab-timeout-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# BOSS 沟通页超时修复评审结算

## 结论

评审已完成两轮。实现已解决“周期轮询无条件冷导航”的确定代码问题,并增加有界恢复和行为级编排测试,但交付状态仍应为 **Partial**,不能表述为线上故障已确认消失。

## 已验证

- 首轮修复后,`reply_unread` 目标测试运行结果为 9 passed、0 failed。
- `cargo check --manifest-path src-tauri/Cargo.toml` 通过。
- `pnpm run build` 通过。
- 前端测试 22 个文件、202 条测试通过。
- 行为测试覆盖:已就绪零导航、首次成功一次导航、首次等待失败后恢复成功恰好两次导航、两次等待失败终止且保留两段错误上下文。

## 评审后追加

- 增加“首次等待失败且恢复导航失败”测试,断言两次导航、一次等待,并保留首次等待及恢复导航错误。
- 修正文档措辞:重复冷导航为高概率诱因,不再声称未经真实环境验证的唯一根因或线上治愈。

## 未验证 / 阻塞证据

- 新增最后一条测试后的重验未完成:第一次因 Windows MSVC `LNK1318` PDB LIMIT 链接失败;再次尝试因磁盘空间不足(os error 112)失败。两次均是构建环境失败,不是测试断言失败,但新增测试仍没有绿色运行证据。
- 没有旧实现上同一行为测试的红灯命令输出;原运行日志和旧代码无条件 `page.get` 只能作为故障证据,不能冒充严格红→绿记录。
- 没有修复版本在真实 BOSS owned tab 上连续轮询的运行日志,因此无法验证真实登录态、风控页、陈旧 DOM 和接口抖动场景。
- 全仓 `cargo fmt --check` 受既存格式差异影响;lint 和独立 typecheck 未配置/未单独验证。

## 发布建议

暂不标记 release-ready。清理构建磁盘空间后应串行重跑目标 Rust 测试;随后在受控 BOSS 账号上观察至少若干轮日志,确认出现“沟通页面已就绪,复用当前页面”,并验证首次加载失败最多恢复一次且后续能进入未读列表或明确终止。
Loading
Loading