From 8bafa24ca077cb969d95bd2a95d2b357df50de18 Mon Sep 17 00:00:00 2001 From: hy Date: Fri, 10 Apr 2026 10:07:29 +0800 Subject: [PATCH] Remove test report flow and rename log contract --- AGENTS.md | 2 +- doc/project-structure.md | 4 +- doc/test-plan/ai-test.md | 2 +- doc/test-plan/settings-test.md | 2 +- doc/test-plan/workbench-test.md | 2 +- doc/test.md | 205 ++---------------- .../live/human-risk-report-draft-live.test.ts | 84 ++++++- tests/ai/tool/logHelpers.ts | 2 +- tests/harness/backend/artifactCollector.ts | 2 +- tests/harness/backend/run-backend-case.ts | 2 +- tests/harness/backend/seedManifest.ts | 2 +- tests/harness/backend/test-types.ts | 4 +- ...report-contract.ts => run-log-contract.ts} | 0 tests/harness/core/write-run-log.ts | 2 +- tests/harness/e2e/run-e2e-case.ts | 2 +- tests/report/ai/report.md | 23 -- tests/report/settings/.gitkeep | 0 tests/report/settings/report.md | 141 ------------ tests/report/workbench/.gitkeep | 0 vitest.backend.config.mts | 3 +- vitest.backend.live.config.mts | 3 +- vitest.e2e.config.mts | 2 +- vitest.renderer.config.mts | 2 +- 23 files changed, 107 insertions(+), 384 deletions(-) rename tests/harness/core/{report-contract.ts => run-log-contract.ts} (100%) delete mode 100644 tests/report/ai/report.md delete mode 100644 tests/report/settings/.gitkeep delete mode 100644 tests/report/settings/report.md delete mode 100644 tests/report/workbench/.gitkeep diff --git a/AGENTS.md b/AGENTS.md index 3881147f..76d9b8e8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,7 @@ - 当涉及 human live 的 docx / KB 混合场景测试设计时,必须阅读 `doc/test-plan/ai-test.md` - 当涉及 Workbench 测试时,必须阅读 `doc/test-plan/workbench-test.md` - 当涉及 Settings 测试时,必须阅读 `doc/test-plan/settings-test.md` -- 当涉及测试用例编写,测试规范时,必须阅读 `doc/test.md` +- 当涉及测试用例编写、runner、raw logs 或日志分析时,必须阅读 `doc/test.md` ### 1.4 prd产品文档相关 - 当涉及 Workbench 的产品需求、交互、工作区资料范围或验收标准时,必须阅读 `doc/prd/workbench.md` diff --git a/doc/project-structure.md b/doc/project-structure.md index b34a92c5..4867e163 100644 --- a/doc/project-structure.md +++ b/doc/project-structure.md @@ -73,14 +73,14 @@ tests/ # 自动化测试 ## 6. 测试目录规则 -- `tests/harness/**` 只放可复用的测试基础设施,不承载旧 suite 治理逻辑或旧 report 契约。 +- `tests/harness/**` 只放可复用的测试基础设施,不承载旧 suite 治理逻辑或旧分析文档契约。 - `tests/fixtures/**` 只放长期复用的输入样本,不混入运行产物。 - `tests/ai/**` 只放 AI formal tests。 - `tests/unit/**` 放长期保留、但不进入 formal test-plan 的 unit / helper / schema / prompt 类测试。 - `tests/workbench/**` 按 workbench PRD 模块组织正式测试。 - `tests/settings/**` 按 settings PRD 模块组织正式测试。 - `tests/kb-search/**` 预留给检索链路测试;`tests/temp/**` 仅放按需临时排查用例。 -- `tests/logs/**` 只放每次运行的原始日志;`tests/report/**` 只放按 domain 维护的正式分析文档。 +- `tests/logs/**` 只放每次运行的原始日志;raw logs 之外不再维护测试专用正式分析目录。 - 测试目录统一使用 kebab-case,运行产物不得反向成为测试发现入口。 ## 7. 文档目录规则 diff --git a/doc/test-plan/ai-test.md b/doc/test-plan/ai-test.md index 79578cce..2963f635 100644 --- a/doc/test-plan/ai-test.md +++ b/doc/test-plan/ai-test.md @@ -3,7 +3,7 @@ ## 1. 总体目标 - 本计划用于定义 AI 域正式测试的范围与领域特有规则。 -- 正式 / temp 准入、runner、raw logs、report 与正式 case 共享字段,统一遵循 `doc/test.md`。 +- 正式 / temp 准入、runner、raw logs 与正式 case 共享字段,统一遵循 `doc/test.md`。 - AI 正式测试只围绕两类稳定对象治理: 1. `tool` 2. `human` diff --git a/doc/test-plan/settings-test.md b/doc/test-plan/settings-test.md index d4f876da..1ef66cb8 100644 --- a/doc/test-plan/settings-test.md +++ b/doc/test-plan/settings-test.md @@ -6,7 +6,7 @@ Settings 正式测试统一对齐 [settings.md](/Users/test/work-space/NCurator-Desktop/doc/prd/settings.md),新增、调整或验收结论都应引用对应的 `SET-*` 需求编号与验收编号。 -正式 / temp 准入、runner、raw logs、report 与正式 case 共享字段,统一遵循 `doc/test.md`。 +正式 / temp 准入、runner、raw logs 与正式 case 共享字段,统一遵循 `doc/test.md`。 ## 2. Suite 设计 diff --git a/doc/test-plan/workbench-test.md b/doc/test-plan/workbench-test.md index 5783c130..72284a87 100644 --- a/doc/test-plan/workbench-test.md +++ b/doc/test-plan/workbench-test.md @@ -6,7 +6,7 @@ workbench 正式测试统一对齐 [workbench.md](/Users/test/work-space/NCurator-Desktop/doc/prd/workbench.md),新增、调整或验收结论都应引用对应的 `WB-*` 需求编号与验收编号。 -正式 / temp 准入、runner、raw logs、report 与正式 case 共享字段,统一遵循 `doc/test.md`。 +正式 / temp 准入、runner、raw logs 与正式 case 共享字段,统一遵循 `doc/test.md`。 ## 2. Suite 设计 diff --git a/doc/test.md b/doc/test.md index 254754f1..07af290e 100644 --- a/doc/test.md +++ b/doc/test.md @@ -3,15 +3,14 @@ ## 1. 文档定位 - 本文是 NCurator-Desktop 的唯一测试总规范。 -- 本文负责定义测试体系总览、正式 case 准入、正式测试闭环、runner、raw logs 与 report 契约。 +- 本文负责定义测试体系总览、正式 case 准入、正式测试闭环、runner 与 raw logs 契约。 - 各业务域的 suite 列表、正式 case 定义与领域特有规则,只在对应 `doc/test-plan/**` 中维护,本文不重复登记 case 清单。 - 如果 case 覆盖的是用户可见功能,还必须先对齐对应 `doc/prd/**`。 - 如果只记一件事:写测试前先判断这是正式长期回归 case,还是一次性临时排查 case。 -正式测试体系只沉淀两层长期产物: +正式测试体系只沉淀一层长期产物: - 原始日志:`tests/logs/**` -- 正式分析文档:`tests/report//report.md` 正式测试样例只记录事实,不直接写失败原因分析、优化建议或能力判断。 @@ -20,7 +19,7 @@ ### 2.1 正式 case 与临时 case - 正式长期回归 case - - 用于长期维护、参与 gating、进入正式 report。 + - 用于长期维护、参与 gating。 - 必须进入正式测试闭环。 - 临时排查 case - 只用于一次性排查、验证猜想、临时复现或补上下文。 @@ -28,7 +27,7 @@ - 默认策略 - 用户没有明确要求“补正式长期 case”时,默认先写 `tests/temp/**`。 - 只要还在排查、验证猜想、试运行 fixture 或尚未确定要长期维护,一律先放 `tests/temp/**`。 - - 只有确认要长期维护、参与 gating 或进入正式 report 的 case,才进入正式测试目录。 + - 只有确认要长期维护、参与 gating 的 case,才进入正式测试目录。 ### 2.2 目录结构 @@ -43,13 +42,6 @@ tests/ kb-search/ temp/ logs/ - report/ - ai/ - report.md - workbench/ - report.md - settings/ - report.md ``` 规则: @@ -61,7 +53,7 @@ tests/ - 各 domain 的 `suite` 列表与归属,只在对应 `doc/test-plan/**` 中定义。 - 当某个 `suite` 不需要继续细分时,正式 case 可以直接放在该 `suite` 目录下。 - `tests/unit/**` 用于长期保留、但不进入 `doc/test-plan/**` 正式治理的 unit / helper / schema / prompt 类测试。 -- `tests/temp/**` 默认不参与 gating,也不参与正式 report 汇总。 +- `tests/temp/**` 默认不参与 gating,也不沉淀正式长期产物。 - 除 `tests/temp/**` 外,`tests/**` 中的正式测试目录只允许放已在 `doc/test-plan/**` 登记的 case。 ### 2.3 稳定映射模型 @@ -75,7 +67,7 @@ tests/ - `suite` 下可选子目录。 - 只有同一 `suite` 内确实需要继续分层时才创建。 - `case` - - 最终测试文件,对应唯一 `caseId`、唯一日志目录和唯一 report 归属。 + - 最终测试文件,对应唯一 `caseId` 与唯一日志目录。 - `type` - 测试类型只通过文件名体现。 - 普通测试默认视为 `backend`;文件名包含 `.e2e.test.ts` 时视为 `e2e`。 @@ -91,7 +83,7 @@ tests/ - 如果 case 覆盖的是用户可见功能,`How / Oracle` 必须映射到对应 `doc/prd/**` 的需求编号与验收编号。 - 如果 PRD 的功能入口、交互流程、状态反馈或验收口径发生变化,必须先更新对应 `doc/prd/**`,再更新 `doc/test-plan/**` 与测试代码。 - 如果实现行为变更导致正式 case 预期变化,必须先更新对应 `doc/test-plan/**`,再修改测试代码。 -- 每个正式 `caseId` 都必须稳定映射到唯一测试文件、唯一日志目录和唯一 report 归属。 +- 每个正式 `caseId` 都必须稳定映射到唯一测试文件与唯一日志目录。 ### 3.2 正式 case 共享字段 @@ -161,7 +153,7 @@ tests/ 4. 再写或调整 `tests/**` 中的正式测试代码。 5. 通过 `scripts/test-workflow.mjs` 执行并产生日志。 6. 先看 `timeline.jsonl`,不足时再看 `runtime-events.jsonl`、`meta.json` 与 `artifacts.json`。 -7. 最后基于 `tests/logs//**` 更新 `tests/report//report.md`。 +7. 最后基于 raw logs 回流结论,决定是否需要更新 `doc/test-plan/**` 或实现代码。 ### 4.2 runner 与常用命令 @@ -178,7 +170,6 @@ runner 不负责: - 写事实汇总稿。 - 写失败原因分析。 - 写优化建议。 -- 更新正式 `report.md`。 当前常用命令按域收口如下: @@ -223,17 +214,11 @@ runner 支持的过滤参数: - 必要时回看 `meta.json` 与 `artifacts.json`,确认 run 摘要、统计值和附件索引。 - 所有分析结论都必须可回溯到 raw logs 与 artifacts,不得脱离证据做推断。 -### 4.4 更新正式 report - -- 正式 report 固定更新 `tests/report//report.md`。 -- report 只能基于 `tests/logs//**` 及其附件生成;`tests/temp/**` 不进入正式 report。 -- report 负责沉淀当前现状分析、失败模式和下一步建议,但不能替代 raw logs 本身。 - -### 4.5 结论回流 +### 4.4 结论回流 - 如果问题出在 case 定义、验收口径或阶段边界,必须先改 `doc/test-plan/**`,再改测试代码。 - 如果只是实现缺陷或回归问题,可在保持 case 规格不变的前提下修实现并重跑。 -- report 中已有结论若被新 run 推翻,应以最新 raw logs 重新分析并更新,不保留无证据的旧判断。 +- 任何分析结论若被新 run 推翻,都应以最新 raw logs 重新分析,不保留无证据的旧判断。 ## 5. runner 与原始产物契约 @@ -356,7 +341,7 @@ tests/logs////// - 范围固定为完整 runtime 原始事件流。 - 普通测试与 e2e 的采集路径可以不同,但最终落盘契约必须一致。 - `runtime-events.jsonl` 始终写出;如果本次 run 没有 runtime 事件,则写空文件。 -- 当 `Oracle`、断言 `data`、`timeline.jsonl` 或 report 仍不足以解释失败原因时,必须继续回看 `runtime-events.jsonl`。 +- 当 `Oracle`、断言 `data` 或 `timeline.jsonl` 仍不足以解释失败原因时,必须继续回看 `runtime-events.jsonl`。 ### 5.5 `artifacts.json` @@ -410,179 +395,17 @@ tests/logs////// - 生成位于 `artifacts/playwright/report/index.html` 的 HTML 诊断页。 - 默认不保留 video。 -## 6. 正式 report 契约 - -### 6.1 位置与作用 - -- `report` 是正式测试闭环中的最终分析产物;前提是对应 domain 已先生成可回看的 raw logs。 -- 当前正式分析文档固定放在: - -```text -tests/report// - report.md -``` - -- `report.md` 是当前业务域唯一正式分析报告。 -- `report.md` 只基于 `tests/logs//**` 与 artifacts 写出当前现状分析。 - -### 6.2 `report.md` 建议结构 - -- 顶层先写 `总览` -- `总览` 至少包含: - - `分析范围` - - `总体结论` - - `下一阶段建议` -- `总览` 之后按 suite / groups 展开 -- 每个实际分析节点至少包含: - - `证据` - - `通过率` - - `失败分析` - - `当前评估` - - `下一步建议` - -### 6.3 `report.md` 格式约束 - -- 顶层标题使用 `# 域测试报告`。 -- 顶层必须先有 `## 总览`。 -- `总览` 下固定小节顺序: - - `### 分析范围` - - `### 总体结论` - - `### 下一阶段建议` -- `总体结论` 中的统计口径固定拆成两类: - - `历史总数据` - - `最新总数据` -- `历史总数据` 基于当前 analysis window 内全部 raw runs 统计。 -- `最新总数据` 每个 case 只看最新一轮 run 的修复后统计。 -- suite 之下按目录树继续展开: - - suite 使用 `##` - - suite 下第一层 group 使用 `###` - - 更深层 group 继续按 Markdown 标题层级递增 -- 每个实际分析节点都必须包含以下固定小节,顺序保持一致: - - `证据` - - `通过率` - - `失败分析` - - `当前评估` - - `下一步建议` -- `证据` 默认只列出能定位该条证据的最小信息,例如 `caseId`、`runId`、`status`。 -- 不要在 report 正文里机械展开 `meta.json`、`timeline.jsonl`、`runtime-events.jsonl`、`artifacts.json` 这些文件名。 -- 只有当失败分析或结论明确依赖某个关键附件时,才额外补充附件名称或用途说明。 -- `通过率` 只写当前节点覆盖范围内的统计,不混入其他节点数据。 -- `通过率` 固定拆成两组: - - `历史总数据`:`totalRuns`、`passedRuns`、`failedRuns`、`historicalSuccessRate` - - `最新总数据`:`latestCaseCount`、`latestPassedCases`、`latestFailedCases`、`latestSuccessRate` -- `历史总数据` 与 `最新总数据` 不得混写成同一个 successRate 口径。 -- `失败分析` 在没有 failed run 时应明确写“当前没有 failed run,因此无法给出失败模式结论”。 -- `当前评估` 负责总结当前状态和主要不足。 -- `下一步建议` 只写基于现有证据能支撑的下一步建议。 - -### 6.4 `report.md` 最小示例 - -```md -# Workbench 域测试报告 - -## 总览 - -### 分析范围 - -- raw logs 范围: 当前仓库内 `tests/logs/workbench/**` -- 已分析 scope: `workbench/`、`workbench/` - -### 总体结论 - -- 历史总数据: `2` 次 raw runs,其中 `2` 次 passed、`0` 次 failed,historicalSuccessRate=`100.0%` -- 最新总数据: `2 / 2` 个 case 的最新一轮 run 为 passed,latestSuccessRate=`100.0%` -- 当前结论: 当前已覆盖一个普通样例和一个 e2e smoke,但剩余 suite 仍待补齐。 - -### 下一阶段建议 - -- 先补 `suite-a` 的边界收敛 -- 再补 `suite-b` 的主线闭环 - -## - -### 证据 - -- `workbench-suite-a-basic` | type=`backend` | run=`20260315-101530-112` | status=`passed` - -### 通过率 - -- 历史总数据: - - totalRuns: 1 - - passedRuns: 1 - - failedRuns: 0 - - historicalSuccessRate: 100.0% -- 最新总数据: - - latestCaseCount: 1 - - latestPassedCases: 1 - - latestFailedCases: 0 - - latestSuccessRate: 100.0% - -### 失败分析 - -- 当前没有 failed run,因此无法给出失败模式结论。 - -### 当前评估 - -- suite-a 的基础路径已稳定产出 raw logs。 -- 当前不足是边界场景覆盖仍不足。 - -### 下一步建议 - -- 增加 `workbench-suite-a-edge-1` -- 增加 `workbench-suite-a-edge-2` - -## - -### 证据 - -- `workbench-suite-b-smoke.e2e` | type=`e2e` | run=`20260315-103002-008` | status=`passed` -- 关键附件: playwright trace - -### 通过率 - -- 历史总数据: - - totalRuns: 1 - - passedRuns: 1 - - failedRuns: 0 - - historicalSuccessRate: 100.0% -- 最新总数据: - - latestCaseCount: 1 - - latestPassedCases: 1 - - latestFailedCases: 0 - - latestSuccessRate: 100.0% - -### 失败分析 - -- 当前没有 failed run,因此无法给出失败模式结论。 - -### 当前评估 - -- suite-b 的 e2e smoke 主链路已可用。 -- 当前不足是剩余验收分支仍未纳入。 - -### 下一步建议 - -- 补充 `suite-b` 的验收分支 1 -- 补充 `suite-b` 的验收分支 2 -``` - -约束: - -- report 只引用 raw logs 与 artifacts 作为证据来源。 -- report 可以做分析与建议,但不得写入没有日志依据的推断。 - -## 7. 明确禁止与常见误区 +## 6. 明确禁止与常见误区 明确禁止: - 测试样例直接输出失败原因分析。 -- runner 自动调用测试所用 AI 模型生成 report。 -- report 写入没有日志依据的推断。 +- 脱离 raw logs 与 artifacts 写入没有证据依据的分析结论。 - 为单个 runner 或单种工具单独再设计一套平行 raw log 契约。 常见误区: - 把 `tests/unit/**` 当成 formal domain case 管理。 -- 把 `tests/temp/**` 的结果直接写进正式 report。 +- 把 `tests/temp/**` 的结果直接当成正式长期结论。 - 在 `timeline.jsonl` 中倾倒底层噪音,而不是保留高价值语义事件。 - 在没有更新 `doc/test-plan/**` 的情况下直接修改正式 case 预期。 diff --git a/tests/ai/human/live/human-risk-report-draft-live.test.ts b/tests/ai/human/live/human-risk-report-draft-live.test.ts index 1d39796e..d27cefdf 100644 --- a/tests/ai/human/live/human-risk-report-draft-live.test.ts +++ b/tests/ai/human/live/human-risk-report-draft-live.test.ts @@ -8,7 +8,36 @@ import { seedRiskReportKb, seedRiskReportWorkspace } from '../../../harness/backend/aiLiveTestData' -import { filterAiRunEventsByType } from '../testUtils' +import { filterAiRunEventsByType, hasKbToolCall } from '../testUtils' + +type DocxApplyOpsResult = { + changedBlocks?: Array<{ + blockId?: string + beforeText?: string + afterText?: string + }> +} + +const mentionsPreviewReady = (text: string): boolean => /(可预览|预览|preview)/i.test(text) + +const mentionsOriginalPreserved = (text: string): boolean => + /(未|不会|没有).{0,10}(覆盖|改写|修改).{0,10}(原(文件|模板)|原始模板|模板文件|源文件)/.test(text) || + /(保留|保持).{0,10}(原(文件|模板)|原始模板|模板文件|源文件).{0,6}(不动|不变)/.test(text) + +const hasExpectedRiskReportChanges = (changedBlocks: readonly DocxApplyOpsResult['changedBlocks'][number][]) => + changedBlocks.length === 2 && + changedBlocks.some( + (block) => + block.blockId === 'b:1' && + /风险结论/.test(block.beforeText || '') && + /待跟进/.test(block.afterText || '') + ) && + changedBlocks.some( + (block) => + block.blockId === 'b:2' && + /负责人说明/.test(block.beforeText || '') && + /Alice/.test(block.afterText || '') + ) describe('ai human live backend', () => { it('human-risk-report-draft-live', async () => { @@ -61,6 +90,11 @@ describe('ai human live backend', () => { const toolResults = filterAiRunEventsByType(result.events, 'tool_call_result') const toolNames = toolResults.map((event) => event.toolName) + const latestDocxApplyOpsEvent = toolResults + .filter((event) => event.toolName === 'docx_apply_ops') + .at(-1) + const docxApplyOps = (latestDocxApplyOpsEvent?.result?.data as DocxApplyOpsResult | undefined) || {} + const changedBlocks = docxApplyOps.changedBlocks || [] const docxArtifacts = result.output?.artifacts?.filter( (artifact) => @@ -77,23 +111,55 @@ describe('ai human live backend', () => { runtime.assertThat( result.output?.status === 'completed' && toolNames.includes('terminal_run_command') && - toolNames.some((toolName) => toolName.startsWith('kb_')) && + hasKbToolCall(result.events) && toolNames.includes('docx_open') && toolNames.includes('docx_apply_ops') && - toolNames.includes('docx_render_preview') && - docxArtifacts.length > 0 && - templateUnchanged && + toolNames.includes('docx_render_preview'), + { + name: 'human-live-risk-report-runs-required-tool-chain', + message: 'live human complex case 应通过 terminal、KB 与 docx 真实工具链完成周报草稿任务。', + data: { + toolNames, + summary: result.output?.summary, + deliveryMarkdown: result.output?.deliveryMarkdown, + artifacts: result.output?.artifacts + } + } + ) + + runtime.assertThat(docxArtifacts.length > 0 && templateUnchanged, { + name: 'human-live-risk-report-produces-preview-without-overwriting-template', + message: 'live human complex case 应生成 preview/draft artifact,且原模板文件不能被覆盖。', + data: { + toolNames, + templatePath: result.workspaceSeed.templatePath, + artifacts: result.output?.artifacts + } + }) + + runtime.assertThat(hasExpectedRiskReportChanges(changedBlocks), { + name: 'human-live-risk-report-updates-risk-and-owner-placeholders', + message: 'live human complex case 应把模板中的风险结论和负责人说明两处占位符替换为实际内容。', + data: { + changedBlocks, + toolNames + } + }) + + runtime.assertThat( + /weekly-risk-report-template\.docx/.test(deliveryText) && /风险结论/.test(deliveryText) && /负责人(说明)?/.test(deliveryText) && /Weekly Risk Summary\.md/.test(deliveryText) && /Owner Note\.md/.test(deliveryText) && - /(预览|preview)/i.test(deliveryText) && - /(未覆盖原文件|原文件未被覆盖|未覆盖原件)/.test(deliveryText), + mentionsPreviewReady(deliveryText) && + mentionsOriginalPreserved(deliveryText), { - name: 'human-live-completes-risk-report-draft-through-real-tool-chain', - message: 'live human complex case 应通过 terminal、KB 与 docx 真实工具链完成周报草稿任务。', + name: 'human-live-risk-report-delivery-explains-user-facing-outcome', + message: 'live human complex case 的最终交付应从用户视角说明模板、两处修改、依据来源、预览产物和未覆盖原文件。', data: { toolNames, + changedBlocks, summary: result.output?.summary, deliveryMarkdown: result.output?.deliveryMarkdown, artifacts: result.output?.artifacts diff --git a/tests/ai/tool/logHelpers.ts b/tests/ai/tool/logHelpers.ts index 74a9ff57..33614d2e 100644 --- a/tests/ai/tool/logHelpers.ts +++ b/tests/ai/tool/logHelpers.ts @@ -1,7 +1,7 @@ import fs from 'node:fs/promises' import path from 'node:path' import { resolveRunLogDir } from '../../harness/backend/write-run-log' -import type { TestArtifactsIndex, TestRunMeta } from '../../harness/core/report-contract' +import type { TestArtifactsIndex, TestRunMeta } from '../../harness/core/run-log-contract' export const readCapturedRunLog = async (input: { scope: string diff --git a/tests/harness/backend/artifactCollector.ts b/tests/harness/backend/artifactCollector.ts index ed521b17..4014d134 100644 --- a/tests/harness/backend/artifactCollector.ts +++ b/tests/harness/backend/artifactCollector.ts @@ -1,7 +1,7 @@ import { cp, mkdir } from 'node:fs/promises' import path from 'node:path' import type { AiRunEvent } from '../../../src/shared/types' -import type { TestArtifact } from '../core/report-contract' +import type { TestArtifact } from '../core/run-log-contract' import { resolveRunArtifactsDir } from './write-run-log' const sanitizeFileName = (value: string): string => { diff --git a/tests/harness/backend/run-backend-case.ts b/tests/harness/backend/run-backend-case.ts index 3e0c591c..ce43e4ef 100644 --- a/tests/harness/backend/run-backend-case.ts +++ b/tests/harness/backend/run-backend-case.ts @@ -19,7 +19,7 @@ import { type TestLogEvent, type TestRunMeta, type TestRunStatus -} from '../core/report-contract' +} from '../core/run-log-contract' const fixturesRoot = path.resolve(process.cwd(), 'tests', 'fixtures') diff --git a/tests/harness/backend/seedManifest.ts b/tests/harness/backend/seedManifest.ts index 1baabd6d..45ae1af6 100644 --- a/tests/harness/backend/seedManifest.ts +++ b/tests/harness/backend/seedManifest.ts @@ -6,7 +6,7 @@ import type { SeedKbDocumentInput, SeedWorkspaceFileRecord } from './test-types' -import type { TestArtifact } from '../core/report-contract' +import type { TestArtifact } from '../core/run-log-contract' import { resolveRunArtifactsDir } from '../core/write-run-log' export const BACKEND_SEED_MANIFEST_SCHEMA_VERSION = 1 as const diff --git a/tests/harness/backend/test-types.ts b/tests/harness/backend/test-types.ts index a009d1f3..ad6bacb5 100644 --- a/tests/harness/backend/test-types.ts +++ b/tests/harness/backend/test-types.ts @@ -27,9 +27,9 @@ import type { TestType, TestLogEvent, TestRunMeta -} from '../core/report-contract' +} from '../core/run-log-contract' -export type { TestDomain, TestType, TestLogEvent, TestRunMeta } from '../core/report-contract' +export type { TestDomain, TestType, TestLogEvent, TestRunMeta } from '../core/run-log-contract' export type ApprovalPolicy = 'auto-approve' | 'deny-medium-high' | 'deny-all' diff --git a/tests/harness/core/report-contract.ts b/tests/harness/core/run-log-contract.ts similarity index 100% rename from tests/harness/core/report-contract.ts rename to tests/harness/core/run-log-contract.ts diff --git a/tests/harness/core/write-run-log.ts b/tests/harness/core/write-run-log.ts index 6d37e33b..ea840f40 100644 --- a/tests/harness/core/write-run-log.ts +++ b/tests/harness/core/write-run-log.ts @@ -7,7 +7,7 @@ import { type TestArtifact, type TestLogEvent, type TestRunMeta -} from './report-contract' +} from './run-log-contract' import type { PersistedSeedManifest } from '../backend/seedManifest' const pad2 = (value: number): string => String(value).padStart(2, '0') diff --git a/tests/harness/e2e/run-e2e-case.ts b/tests/harness/e2e/run-e2e-case.ts index f0e6e94d..baeb40a8 100644 --- a/tests/harness/e2e/run-e2e-case.ts +++ b/tests/harness/e2e/run-e2e-case.ts @@ -12,7 +12,7 @@ import { type TestLogStatus, type TestRunMeta, type TestRunStatus -} from '../core/report-contract' +} from '../core/run-log-contract' import { createRunId, resolveRunArtifactsDir, writeRunLog } from '../core/write-run-log' import { launchElectronApp, type E2ERuntimeSignals } from './electronApp' diff --git a/tests/report/ai/report.md b/tests/report/ai/report.md deleted file mode 100644 index 0403d279..00000000 --- a/tests/report/ai/report.md +++ /dev/null @@ -1,23 +0,0 @@ -# AI 域测试报告 - -## 总览 - -- raw logs 范围:当前仓库内 `tests/logs/ai/**` -- 本次纳入分析的 suite:`tool`、`human` -- 当前未纳入分析的范围:`human/live` - -### 总体结论 - -- 当前正式 AI 基线已经收敛到 `tool + human` 两类 suite。 -- `tool` 继续提供 docx、kb、terminal、hand 的稳定底座。 -- `human/mock-llm` 继续作为 human-only runtime 的正式回归基线。 - -## tool - -- 当前 `tool` suite 仍作为 AI 域稳定正式基线。 -- 后续继续围绕真实工具、真实 artifact、真实审批边界维护。 - -## human - -- 当前 `human/mock-llm` 是 AI 主链的正式回归入口。 -- 后续优先补充和维护 `AiRunService -> human` 直达入口 case 与 `human/live` 复杂任务 case。 diff --git a/tests/report/settings/.gitkeep b/tests/report/settings/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/report/settings/report.md b/tests/report/settings/report.md deleted file mode 100644 index 5bc07fb0..00000000 --- a/tests/report/settings/report.md +++ /dev/null @@ -1,141 +0,0 @@ -# Settings 域测试报告 - -## 总览 - -### 分析范围 - -- raw logs 范围:当前仓库内 `tests/logs/settings/**` -- 本次分析窗口:当前仓库内 Settings 域全部 raw runs -- 本次纳入分析的 suite:`model`、`workspace`、`web` -- 当前未纳入 raw logs 的计划 suite:`vector` - -### 总体结论 - -- 历史总数据:`totalRuns=95`、`passedRuns=68`、`failedRuns=27`、`historicalSuccessRate=71.6%` -- 最新总数据:`latestCaseCount=17`、`latestPassedCases=17`、`latestFailedCases=0`、`latestSuccessRate=100.0%` -- 当前结论:本轮新增并收敛了 `model-page-load-active-config`、`model-delete-config-feedback`、`workspace-page-load-default-selection`、`workspace-add-selection-flow`、`workspace-empty-tree-legacy-hints`、`web-refresh-one-source` 六条正式 case。当前进入 raw logs 的 17 条 Settings 正式 case 在 latest 口径下已全部为 `passed`,覆盖 `model`、`workspace`、`web` 三个 suite 的首批核心用户链路;`vector` suite 仍然没有正式 raw logs,尚未进入当前 report 覆盖面。 - -### 下一阶段建议 - -- 继续补齐 `model` 中围绕配置列表契约与 `check-llm-config` 变更事件的 backend case -- 继续补齐 `workspace` 中围绕扫描契约、加载模式契约、打开路径契约和移除后数据源收敛的 backend case -- 继续补齐 `web` 中围绕当前可见列表批量抓取范围和外链打开契约的 backend case -- 启动 `vector` suite 的正式 case 实现与 raw logs 闭环 - -## model - -### 证据 - -- `model-create-edit-form` | `20260327-185017-046` | `passed` -- `model-delete-config-feedback` | `20260327-185014-125` | `passed` -- `model-enable-switch-current` | `20260327-185021-550` | `passed` -- `model-first-config-auto-activate` | `20260327-185019-432` | `passed` -- `model-page-load-active-config` | `20260327-185023-169` | `passed` - -### 通过率 - -- 历史总数据:`totalRuns=37`、`passedRuns=27`、`failedRuns=10`、`historicalSuccessRate=73.0%` -- 最新总数据:`latestCaseCount=5`、`latestPassedCases=5`、`latestFailedCases=0`、`latestSuccessRate=100.0%` - -### 失败分析 - -- 历史 failed run 共 `10` 次: -- `model-create-edit-form` | `20260327-175759-024` | `failed` -- `model-create-edit-form` | `20260327-180058-496` | `failed` -- `model-create-edit-form` | `20260327-180335-189` | `failed` -- `model-delete-config-feedback` | `20260327-184218-120` | `failed` -- `model-delete-config-feedback` | `20260327-184522-625` | `failed` -- `model-delete-config-feedback` | `20260327-184705-691` | `failed` -- `model-delete-config-feedback` | `20260327-184819-583` | `failed` -- `model-enable-switch-current` | `20260327-175834-037` | `failed` -- `model-first-config-auto-activate` | `20260327-175906-781` | `failed` -- `model-first-config-auto-activate` | `20260327-180132-257` | `failed` -- 上述存在历史失败的 4 条 case,其最新 run 均已转为 `passed`,因此当前 suite 没有 latest failed case。 - -### 当前评估 - -- `model` suite 已覆盖页面首屏初始化、新增/编辑表单、首条配置自动激活、手动切换当前模型、删除成功与删除失败反馈五条核心链路。 -- 从 latest 口径看,当前 raw logs 已经支持 `SET-MODEL-001`、`SET-MODEL-002`、`SET-MODEL-003`、`SET-MODEL-005` 的首批正式验收闭环。 - -### 下一步建议 - -- 补齐 `model-config-list-contract` -- 补齐 `model-active-config-change-event` - -## workspace - -### 证据 - -- `workspace-add-selection-flow` | `20260327-184821-653` | `passed` -- `workspace-detail-status-and-error` | `20260327-184848-985` | `passed` -- `workspace-empty-tree-legacy-hints` | `20260327-184826-801` | `passed` -- `workspace-load-by-mode` | `20260327-184838-245` | `passed` -- `workspace-page-load-default-selection` | `20260327-184819-579` | `passed` -- `workspace-remove-from-list` | `20260327-184843-817` | `passed` -- `workspace-scan-progress-refresh` | `20260327-184831-859` | `passed` - -### 通过率 - -- 历史总数据:`totalRuns=36`、`passedRuns=26`、`failedRuns=10`、`historicalSuccessRate=72.2%` -- 最新总数据:`latestCaseCount=7`、`latestPassedCases=7`、`latestFailedCases=0`、`latestSuccessRate=100.0%` - -### 失败分析 - -- 历史 failed run 共 `10` 次: -- `workspace-add-selection-flow` | `20260327-184320-168` | `failed` -- `workspace-add-selection-flow` | `20260327-184523-503` | `failed` -- `workspace-add-selection-flow` | `20260327-184701-806` | `failed` -- `workspace-empty-tree-legacy-hints` | `20260327-184248-489` | `failed` -- `workspace-empty-tree-legacy-hints` | `20260327-184703-790` | `failed` -- `workspace-load-by-mode` | `20260327-180703-475` | `failed` -- `workspace-page-load-default-selection` | `20260327-184212-690` | `failed` -- `workspace-page-load-default-selection` | `20260327-184518-328` | `failed` -- `workspace-remove-from-list` | `20260327-180743-654` | `failed` -- `workspace-scan-progress-refresh` | `20260327-180706-984` | `failed` -- 上述存在历史失败的 5 条 case,其最新 run 均已转为 `passed`,因此当前 suite 没有 latest failed case。 - -### 当前评估 - -- `workspace` suite 已覆盖首屏默认选中、添加选择目录、扫描进度刷新、按模式加载、错误与摘要展示、移除后列表收敛、无文件/旧数据提示七条核心用户链路。 -- 从 latest 口径看,当前 raw logs 已经支持 `SET-WORKSPACE-001`、`SET-WORKSPACE-002`、`SET-WORKSPACE-003`、`SET-WORKSPACE-004`、`SET-WORKSPACE-005`、`SET-WORKSPACE-006`、`SET-WORKSPACE-007` 的首批正式验收闭环。 - -### 下一步建议 - -- 补齐 `workspace-scan-contract`、`workspace-load-mode-contract`、`workspace-open-path-contract`、`workspace-remove-source-contract` - -## web - -### 证据 - -- `web-add-sources-dialog` | `20260327-184518-331` | `passed` -- `web-detail-and-delete` | `20260327-184535-264` | `passed` -- `web-page-load-filter-selection` | `20260327-184521-416` | `passed` -- `web-refresh-all-summary` | `20260327-184529-702` | `passed` -- `web-refresh-one-source` | `20260327-184523-091` | `passed` - -### 通过率 - -- 历史总数据:`totalRuns=22`、`passedRuns=15`、`failedRuns=7`、`historicalSuccessRate=68.2%` -- 最新总数据:`latestCaseCount=5`、`latestPassedCases=5`、`latestFailedCases=0`、`latestSuccessRate=100.0%` - -### 失败分析 - -- 历史 failed run 共 `7` 次: -- `web-page-load-filter-selection` | `20260327-181604-617` | `failed` -- `web-page-load-filter-selection` | `20260327-181836-057` | `failed` -- `web-add-sources-dialog` | `20260327-181608-566` | `failed` -- `web-add-sources-dialog` | `20260327-181839-692` | `failed` -- `web-refresh-all-summary` | `20260327-181643-331` | `failed` -- `web-refresh-all-summary` | `20260327-181913-148` | `failed` -- `web-refresh-one-source` | `20260327-184231-184` | `failed` -- 上述存在历史失败的 4 条 case,其最新 run 均已转为 `passed`;`web-detail-and-delete` 的全部 raw runs 目前均为 `passed`,因此当前 suite 没有 latest failed case。 - -### 当前评估 - -- `web` suite 已覆盖首屏与筛选、批量添加入口、单条重新抓取、全部抓取汇总反馈、详情与删除收敛五条主链路。 -- 从 latest 口径看,当前 raw logs 已经支持 `SET-WEB-001`、`SET-WEB-002`、`SET-WEB-003`、`SET-WEB-004`、`SET-WEB-005` 的首批正式验收闭环。 - -### 下一步建议 - -- 补齐 `web-refresh-visible-list-contract` -- 补齐 `web-open-url-contract` diff --git a/tests/report/workbench/.gitkeep b/tests/report/workbench/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/vitest.backend.config.mts b/vitest.backend.config.mts index 3af46d9a..332924c9 100644 --- a/vitest.backend.config.mts +++ b/vitest.backend.config.mts @@ -7,8 +7,7 @@ export default defineConfig({ 'tests/**/*.e2e.test.ts', 'tests/harness/**', 'tests/fixtures/**', - 'tests/logs/**', - 'tests/report/**' + 'tests/logs/**' ], environment: 'node', globals: true, diff --git a/vitest.backend.live.config.mts b/vitest.backend.live.config.mts index f4c73632..eb74743d 100644 --- a/vitest.backend.live.config.mts +++ b/vitest.backend.live.config.mts @@ -7,8 +7,7 @@ export default defineConfig({ 'tests/**/*.e2e.test.ts', 'tests/harness/**', 'tests/fixtures/**', - 'tests/logs/**', - 'tests/report/**' + 'tests/logs/**' ], environment: 'node', globals: true, diff --git a/vitest.e2e.config.mts b/vitest.e2e.config.mts index 9cc705e2..286f2938 100644 --- a/vitest.e2e.config.mts +++ b/vitest.e2e.config.mts @@ -3,7 +3,7 @@ import { defineConfig } from 'vitest/config' export default defineConfig({ test: { include: ['tests/**/*.e2e.test.ts', 'tests/**/*.e2e.test.tsx'], - exclude: ['tests/harness/**', 'tests/fixtures/**', 'tests/logs/**', 'tests/report/**'], + exclude: ['tests/harness/**', 'tests/fixtures/**', 'tests/logs/**'], environment: 'node', globals: true, fileParallelism: false, diff --git a/vitest.renderer.config.mts b/vitest.renderer.config.mts index bdf6aa13..7702aaaf 100644 --- a/vitest.renderer.config.mts +++ b/vitest.renderer.config.mts @@ -11,7 +11,7 @@ export default defineConfig({ }, test: { include: ['tests/renderer/**/*.test.ts', 'tests/renderer/**/*.test.tsx'], - exclude: ['tests/harness/**', 'tests/fixtures/**', 'tests/logs/**', 'tests/report/**'], + exclude: ['tests/harness/**', 'tests/fixtures/**', 'tests/logs/**'], environment: 'jsdom', globals: true, setupFiles: ['tests/harness/renderer/setup.ts'],