- test-report 追加 §8:根因取证、三层修复、dev 回填实测(4424/4508)、 真实 PI 前向路径验收(消息 4548 免回填直接落归一化 label)、 刷新窗口恢复断言、部署制品核验;一次性会话已撤销 - assets 归档 round2 证据:real-task / message-4548-snapshot / window-round2 / bundle-markers-round2 / forward-verify - CURRENT 集成槽位释放为 idle(taskrun-status-card label 修复已合入 dev) Co-authored-by: Cursor <cursoragent@cursor.com>
9.2 KiB
任务执行状态卡片与刷新持久化 测试报告
一、 测试背景 (Background)
对话启动任务后,进度只以气泡内横向 PhaseEventStrip 展示:无标题、无耗时、无「当前正在做什么」的突出横幅。phaseEvents 不落库,刷新后 completed 任务进度条消失,退化成纯文本。用户要求保留卡片形态,且刷新后不消失、不退化。
二、 测试目标 (Test Objectives)
- 任务气泡渲染竖向时间线
TaskRunCard(标题 + 状态徽章 + 耗时 + 步骤 + 当前阶段)。 - Finalize 将
metadata.task_phase_snapshot写入助手消息;刷新后窗口 API 带回完整快照,卡片可零请求重建。 - 存量无 snapshot 的消息仍可通过
replay_only扩面重放恢复步骤。 - 验收必须走真实
pi-agent(MiniMax-M2.7-highspeed),禁止 stub 冒充交付数据。
三、 测试方案与环境 (Test Plan & Environment)
- OS:linux。分支
feature/taskrun-status-card-2026-09-21,合入本地dev于集成 worktree.worktrees/agent-governance-dev-integration。 ./scripts/env-service.sh dev rebuild(worktree 内通过符号链接复用主仓.env/configs/.env.dev)。- 单元:
go test -short ./internal/taskrun ./internal/ctxmgr;cd web && npm test && npm run build。 - 端到端:为用户 398(陈威)签发一次性会话(验收后立即
revoked_at),项目 6579 /sess-p6579-u398/task_key=bd_intake发起真实任务。
四、 预期结果 (Expected Results)
/health:env=dev、agent_backend=pi-agent、schema_version=60。- 新任务终态助手消息
metadata.task_phase_snapshot含title/steps/duration_ms/status。 GET /api/v1/chat/messages/window同消息带回 snapshot(模拟刷新)。- 前端包含
task-run-card/task_phase_snapshot。 - 旧 run 的
events?replay_only=1仍能吐出 phase 事件。
五、 实际测试结果与判定 (Actual Results & Evaluation)
用例 1:健康与真实 PI
- 测试输入:
curl -sf http://127.0.0.1:8080/health;curl -sf http://127.0.0.1:18865/health - 实际输出:
{"status":"ok","env":"dev","agent_backend":"pi-agent","version":"v1.0","shared_kb_port":5432,"kb_ready":true,"database_ready":true,"schema_version":60,"schema_ready":true,"task_store_ready":true}
pi-agent:ok=true,model_id=MiniMax-M2.7-highspeed。
- 评价判定:PASS
- 性能与耗时:<1s
用例 2:真实任务终态写入 phase 快照
- 测试输入:
POST /api/v1/tasks/runs,project_id=6579,session_id=sess-p6579-u398,task_key=bd_intake,user_message=编写用户初始需求收集表(状态卡验收) - 实际输出:HTTP 202,
run_id=run_1789978731880379297,约 4 分钟后status=pending_author_confirmation,assistant_message_id=4424。 - DB 取样(
chat_messages.id=4424):
has_snap=t title=用户初始需求收集表 duration_ms=244864 steps=4
steps: squad_assembly / step_executing / quality_gate / advisor_briefing(均为 completed)
- 评价判定:PASS(真实 PI 全链路;快照已持久化)
- 性能与耗时:创建 202 ≈0.2s;终态 ≈244s
用例 3:刷新窗口带回卡片数据
- 测试输入:
GET /api/v1/chat/messages/window?session_id=sess-p6579-u398&days=1(同一用户一次性会话) - 实际输出:
window_ok 4424 pending_author_confirmation 用户初始需求收集表 244864 4 - 评价判定:PASS(刷新路径可重建卡片;前端
mapRecordToMessage单测同步覆盖) - 性能与耗时:≈0.3s
用例 4:存量 run 的 replay_only 扩面
- 测试输入:
GET /api/v1/tasks/runs/run_1789975357256493376/events?after_seq=0&replay_only=1 - 实际输出:HTTP 200,
legacy_phase_events=12(含squad_assembly等 phase) - 评价判定:PASS
- 性能与耗时:≈0.2s
用例 5:前端包卡片标记
- 测试输入:容器内
grep task-run-card / task_phase_snapshot于/app/web/dist/assets/index-*.js - 实际输出:
index-m1o_7k1U.js均命中(见 assets/bundle-markers.txt) - 评价判定:PASS
- 性能与耗时:字符串检查一次完成
六、 自动化测试套件汇总 (Test Suite Execution)
go vet ./internal/taskrun/... ./internal/ctxmgr/... ./internal/server/...:通过go test -short ./internal/taskrun ./internal/ctxmgr:通过web npm test:468 + vitest 33 通过web npm run build:通过(tsc + vite)
证据目录:.doc/test-reports/assets/2026-09-21-taskrun-status-card-persistence/
七、 测试结论与后续优化建议 (Conclusion & Next Steps)
达到合入 dev 标准:真实 PI 任务终态写入 task_phase_snapshot,刷新窗口可重建竖向时间线卡片;存量消息仍可 SSE 重放。一次性鉴权会话已撤销。test/main 不晋升;不改 production_ready;项目 143 未改写。
后续可选:运行中任务刷新时把 live phaseEvents 增量写回 metadata(当前依赖 SSE 订阅 + 终态快照);步骤多时时间线折叠。
八、 二轮修复验收:收口后 label 冻结为进度中文案(2026-09-21)
8.1 背景与缺陷取证
一轮验收后用户反馈:任务显示"已完成",但卡片下方步骤仍读作运行中,出现
"贴身业务参谋正在提炼关键决策摘要与风险雷达...(98%)"。DB 取证(chat_messages.id=4424):
步骤 status 均为 completed,但 label 永久冻结为写入时的进度中叙述。
根因:后端 phase_snapshot.go(applyPhasePayload 收口分支 + BuildPhaseSnapshot 终态兜底)
与前端 phaseEventMapper.ts(applyPhaseEvent 三处收口分支)只翻转 status、不改写 label;
label 来自上游 phase.Message 原样拼百分比后缀,落库后不再修正。
8.2 修复内容与自动化回归
fix(taskrun):新增导出NormalizeSettledStep(completed 步骤归一化为短标签 + "已完成", 保留"(第 x/y 步)"结构后缀;failed 有意保留原文案;幂等)。fix(web):settleStep对称归一化 +displayStepLabel渲染层兜底(防历史脏数据)。chore(ops):scripts/backfill_task_phase_snapshot_labels.go历史回填(幂等,支持-dry-run/-id)。- 单元回归:
go test ./internal/taskrun/... ./internal/ctxmgr/...通过(含#4424复现用例、 幂等用例、多步后缀保留用例);web npm test472+33 全绿;tsc --noEmit+npm run build通过。
8.3 历史数据回填实测(dev)
- 回填前取样见
assets/.../backfill-before.txt(4424/4508 共 8 个 completed 步骤全部冻结为 "正在…(NN%)"文案)。 - 执行:
go run ./scripts/backfill_task_phase_snapshot_labels.go(先-dry-run确认目标集) →backfill complete: scanned_candidates=2 updated=2(assets/.../backfill-run.txt)。 - 回填后取样见
assets/.../backfill-after.txt:8 个步骤 label 全部归一化为 "组建小队已完成 / 专员执行已完成 / 质量门禁已完成 / 参谋简报已完成"。 - 幂等验证:二次
-dry-run报告 0 条待变更。
8.4 真实 Agent 全链路验收(红线)
- 环境:dev 容器重建后(
env-service.sh dev rebuild,/healthschema_version=61、agent_backend=pi-agent);pi-runnerMiniMax-M2.7-highspeed(shuimu-pi-agent-devhealthy)。 - 端到端:为用户 398 签发一次性会话(验收后已
revoked_at),POST /api/v1/tasks/runs→ HTTP 202run_1789989929668718353(project_id=6579, task_key=bd_intake, session_id=sess-p6579-u398)。 - 判定关键:本条 run 由新部署代码的 finalize 前向路径直接落库,未经任何回填。
新助手消息
id=4548(status=pending_author_confirmation,耗时duration_ms=340510)快照:
steps:
squad_assembly completed label=组建小队已完成
step_executing completed label=专员执行已完成
quality_gate completed label=质量门禁已完成
advisor_briefing completed label=参谋简报已完成
原始"正在…(NN%)"叙述保留在 detail 字段(供审计),不再出现在 label。
完整快照见 assets/.../message-4548-snapshot-round2.txt,run 记录见 real-task-round2.txt。
- 刷新恢复(模拟 F5):
GET /api/v1/chat/messages/window?session_id=sess-p6579-u398&days=1返回 4548 的 snapshot,4 个 completed 步骤 label 均为静态措辞 (脚本断言无"正在"/"%"残留,WINDOW_API_LABELS_OK;见window-round2.json)。 - 部署制品核验:容器
index.html引用assets/index-CgkGfOP7.js,bundle 内含参谋简报/task-run-card/task_phase_snapshot标记(bundle-markers-round2.txt)。 - 评价判定:PASS(真实 PI 全链路 + 前向路径 + 刷新恢复 + 历史回填四证齐全)
- 一次性会话已撤销(
auth_sessions.revoked_at已置)。
8.5 二轮结论
production_ready不变;test/main 不晋升;项目 143 未触碰。- 新任务不再产生冻结文案;历史脏数据(4424/4508)已由幂等回填脚本修复; 渲染层兜底保证即使回填遗漏也不会出现"已完成却像还在跑"的文案。