---
description: harness-execute 的 Phase 0 环境准备 + Playwright 探测 + 关门检查清单。仅在执行测试前的环境准备阶段读取。
---

# harness-execute 检查清单 — Phase 0 环境准备 + 关门检查

以下检查项确认完了再开始测试。每一项背后都有踩坑经历。

### Wave-A 环境合同（IA-3）

- [ ] 需要可写 DB/栈时：先 `harness_environment.py fingerprint` → `acquire` lease → 再跑测试 → `release`
- [ ] 无 lease 不得占用可写栈（`ENVIRONMENT_LEASE_REQUIRED`）；跨 change 默认可写共享拒绝（`ENVIRONMENT_LEASE_CROSS_CHANGE`）
- [ ] 租约目录：主仓 `.harness/runtime/env-leases/`（与 change 状态目录分离）

#### 0.0 加载项目配置（如存在）与确定变更名

先检查当前项目的测试配置文件（按优先级查找）：

1. `.harness/config/harness-test-config.md`（集中配置目录；旧 skill 目录下的兼容路径已随 harness-test 入口移除而废弃）

如果任一文件存在，**必须先读取并应用其中的配置**。配置文件通常包含：

- **登录端点**：本地无法直接登录时，远程认证服务（如 SSO/Gateway）的登录 URL
- **测试账号**：各权限级别的用户名密码（如 admin、一层组织管理员等）
- **真实测试数据**：有效的部门编码和名称、项目 ID、规则 ID 等
- **环境调整**：需要使用的 profile、需要临时放行的 URL 路径、需要跳过的模块
- **避坑补充**：本项目特有的已知问题和解决方案

**Profile 选择**（从配置文件读取，如无配置则询问用户；按技术栈，Java Spring Boot 为例）：

| Profile | 适用场景 | 配置文件（按技术栈） |
|---------|---------|---------|
| `local` | 连接远程数据库/缓存 | 应用本地配置（如 `application-local.yml`） |
| `local-dev` | 完全本地隔离 | 应用本地隔离配置（如 `application-local-dev.yml`） |

> **关键**：不指定 profile 时默认使用主应用配置文件（如 `application.yml`）中的配置（可能指向生产环境），必须显式指定。启动命令必须包含对应技术栈的 profile 指定参数（如 Spring Boot 的 `--spring.profiles.active=<profile>`）。

然后确定变更名：用 Glob 搜索 `.harness/changes/*/plans/*-plan.md`（**排除 `.harness/archive/*/`**），读取 frontmatter 提取 `change-name`。

#### 0.0-A 资源安全档位（所有测试的硬前置）

- [ ] 默认选择 `safe`，测试命令由 `harness/scripts/harness_test_runner.py` 托管；禁止裸跑整库 discovery 或工具默认无限并发
- [ ] Python `unittest` 使用逐模块隔离模式；每个 `test_*.py` 在独立解释器中串行执行，失败默认立即停止
- [ ] 同项目单实例锁已获得；出现 `TEST_RUN_ALREADY_ACTIVE` 时停止，不得启动第二套测试
- [ ] `HARNESS_TEST_MAX_WORKERS` 为 `1` 或 `2`，且技术栈自身 worker 参数不高于该值
- [ ] 每个模块/命令设置明确超时；超时返回 `TEST_COMMAND_TIMEOUT` 并清理整棵进程树
- [ ] Windows 普通模块使用 kill-on-close Job Object；显式测试 detached service 的模块改用精确 PID 血缘跟踪；其他平台使用独立进程组
- [ ] Windows detached-service 模块执行前 nested-breakaway preflight 已通过；`DETACHED_PROCESS_CAPABILITY_UNAVAILABLE` 时立即停止并切换到允许该能力的执行环境，不逐用例等待超时
- [ ] 任一隔离模式返回 `PROCESS_TREE_ISOLATION_UNAVAILABLE` 时停止资源密集型测试
- [ ] `system` / `full` 属于资源密集型档位：用户明确授权后才传 `--confirm-resource-intensive`；受控 CI 可用 `CI=true`
- [ ] `safe` 不包含服务生命周期和集成模块；`full` 仍按“普通模块 → 资源密集型模块”顺序串行，不得恢复单进程全量 discovery
- [ ] 测试前记录已有工作区状态；测试后状态只允许包含本轮预期变化，不要求删除用户原有变更

#### 0.1 命令执行模式 preflight（⚠️ 必须在编译/启动服务/生成执行器之前执行）

- [ ] 检查 PowerShell 基础命令：`powershell.exe -NoProfile -Command "$PSVersionTable.PSVersion"` 返回 exitCode=0
- [ ] 检查执行器运行时可用性（如 Node 绝对路径）：`powershell.exe -NoProfile -Command "& 'C:\nvm4w\nodejs\node.exe' --version"` 返回 exitCode=0
- [ ] 检查构建工具可用性（如 Maven）：`powershell.exe -NoProfile -Command "mvn -version"` 返回 exitCode=0
- [ ] 检查安全分类器：上述任一命令是否返回"安全分类器暂时不可用" / Auto mode 拦截 → **不应出现**
- [ ] 将通过的 `executorPath` / `powershellVersion` / `buildToolVersion` 写入 `.harness/changes/<change-name>/runtime/preflight.json`
- [ ] **任一情况触发硬停**：原文输出"❌ 命令执行模式不可用：PowerShell/接口测试执行器无法稳定执行..."，**不得继续编译/启动服务/生成执行器，不得长时间等待，不得盲目降级到 Playwright MCP**
- [ ] 用户确认切换权限模式后，**重新执行 0.1**；重试 ≤ 1 次

#### 0.2 fallback 执行器探测（仅在首选执行器不可用时执行）

- [ ] 如果 0.1 已确认首选接口测试执行器可用：标记 `NOT_NEEDED`，**跳过本阶段**，直接使用接口测试执行器
- [ ] 仅当首选执行器不可用时，检查 PowerShell batch runner (`.ps1`) 是否可用
- [ ] 仅当 PowerShell batch 也不可用时，检查 Claude Code 是否暴露 Playwright MCP 工具（`mcp__plugin_playwright_playwright__*` 存在）
- [ ] 检查 `claude mcp list` 中是否有 playwright（如果可以执行命令）
- [ ] 检查 `@playwright/mcp` 是否可启动
- [ ] 检查当前 skill 的 `allowed-tools` 是否允许 Playwright 相关工具
- [ ] 输出 fallback 执行器可用性表格（见 testing-reference.md）
- [ ] 记录决策：接口测试执行器 / PowerShell batch / Playwright MCP browser_evaluate / curl fallback
- [ ] 如果 fallback 不可用，必须写明原因，不得静默改用 curl

#### 0.3 依赖模块预安装检查

> **强制检查，不可跳过。** 即使服务已运行，worktree 中的编译仍可能缺少依赖（服务可能从主目录启动）。

**在编译前检查上游依赖模块是否已安装到本地仓库**（按技术栈，Java/Maven 为例）：

```powershell
powershell.exe -Command "Test-Path '$env:USERPROFILE\.m2\repository\<group-path>\<module>\*\*.jar'"
```

如果缺失，先安装上游依赖：
```powershell
powershell.exe -Command "mvn install -pl <upstream-modules> -am -DskipTests -nsu"
```

#### 0.4 编译确认（按技术栈，Java/Maven 为例）

```powershell
powershell.exe -Command "Test-Path 'target/classes/<package>/<ChangedClass>.class'"
```
编译产物时间戳早于源文件 → 重新编译：
```powershell
powershell.exe -Command "mvn compile -pl <module> -o -q"
```

**编译成功必须有证据**：
- 构建工具输出包含成功标志（如 Maven 的 `BUILD SUCCESS`）才能继续测试
- 如果命令被 hook 拒绝（`Denied` / `PreToolUse:Bash hook error`），停止流程
- 不得在编译失败时继续宣称"准备进入测试阶段"

#### 0.5 认证方案确认

| 方案 | 适用场景 | 操作 |
|------|----------|------|
| A. 配置放行 | 纯本地开发 | 应用配置文件中放行测试接口（如 `permit-all-urls`） |
| B. 本地凭证 | 有本地认证服务 | 通过本地登录接口获取认证凭证 |
| C. 权限降级 | 临时测试 | 无认证上下文时降级为高权限账号 |

> ⚠️ 方案 A 或 C 时，测试完成后确认还原配置。

#### 0.6 请求头确认

所有 HTTP 请求必须带：`Content-Type: application/json; charset=UTF-8` 和租户标识（如项目适用，如 `tenant-id: <从配置读取>`）。

#### 0.7 编码确认

Windows 环境特别注意：
- 不要用 `curl` 发送含中文的请求体（curl 在 Windows 默认用 GBK 编码）
- 优先用接口测试执行器；单次临时请求可用 PowerShell `Invoke-RestMethod`
- curl 仅作为最后兜底，且必须用 UTF-8 JSON body file

#### 0.8 配置文件完整性检查

**如果使用 worktree**，检查配置文件是否完整（按技术栈，Java Spring Boot 为例）：

```powershell
powershell.exe -Command "Test-Path '<worktree-path>/<module>/src/main/resources/application-<profile>.yml'"
```

如果缺失，从主目录复制：
```powershell
powershell.exe -Command "Copy-Item '<main-dir>/<module>/src/main/resources/application-<profile>.yml' '<worktree-path>/<module>/src/main/resources/' -Force"
```

**检查关键配置项**（读取配置文件内容确认，按项目）：
- 外部服务地址（如 `workflow.baseUrl` 或类似属性）— 缺失会导致组件初始化失败
- 服务注册开关（如 `spring.cloud.nacos.discovery.register-enabled: false`）— 缺失会导致线上流量路由到本地
- 接口放行配置（如 `udp.security.permit-all-urls`）— 需包含本次测试的接口路径

#### 0.9 Playwright 远程访问确认

如果接口测试需要通过 Playwright 访问远程服务（如远程认证服务获取凭证），确认 Playwright MCP 配置允许目标地址。

检查 `.mcp.json` 或全局 MCP 配置中 Playwright 的 `allowedOrigins`：
```json
{
  "playwright": {
    "allowedOrigins": ["http://localhost:*", "http://<remote-ip>:*"]
  }
}
```

> 如果 Playwright 无法访问远程地址，降级为 PowerShell Invoke-RestMethod 获取认证凭证。

#### 0.10 服务确认、服务决策门与启动等待

检查服务是否运行（优先使用已知接口，不依赖通用健康端点如 `/actuator/health`）：

```powershell
powershell.exe -NoProfile -Command "Test-NetConnection -ComputerName localhost -Port <port>"
powershell.exe -NoProfile -Command "try { (Invoke-WebRequest -Uri 'http://127.0.0.1:<port>/<context-path>/meta' -UseBasicParsing -TimeoutSec 3).StatusCode } catch { $_.Exception.Message }"
```

**如果端口已有应用服务进程，必须先进入服务决策门（Service Decision Gate），禁止先跑业务接口。**

需要展示：pid、profile、startTime、commandLine、healthResult、serviceFingerprint(match/missing/mismatch)、当前源码是否晚于服务启动时间。

询问用户：

```text
1. 直接复用当前服务
2. 重启服务，使用已知良好测试配置
3. 跳过接口测试，只执行单元测试
4. 停止测试
```

只有 `runtime/service-session.json` 与当前**同时**满足 `moduleInputsHash`/`startCommandHash`/`profile`/`overlayPath` 一致且进程身份（pid 存活 + create time）可确认时，才允许自动复用（§5.3）。任一变化 -> restart；身份无法确认 -> `needs-user-decision`；非 AI 用户进程不自动 kill。否则必须询问。`moduleInputsHash` 来自 CLI `--files` ∪ `serviceStart.inputFiles`，**空输入被拒绝**（不生成空指纹）。

**如果服务未运行**，询问用户：

```text
服务未启动（端口 <port> 无响应）。请选择：
1. AI 启动 — 使用已知良好测试配置，serviceState=AI_STARTED
2. 用户手动启动 — 启动后告诉我继续，serviceState=USER_STARTED
3. 跳过接口测试 — 只运行单元测试，serviceState=NOT_STARTED
4. 停止测试
```

**如果用户选择 AI 启动或 AI 重启**：
1. 从已知良好测试配置读取 module/profile/port/healthUrl/sdkUrl（按项目配置）。
2. 生成 ASCII 运行时配置叠加：`C:/temp/harness-execute-overlay/<change-name>/application-harness-execute.yml`（按技术栈；Java Spring Boot 的 application.yml 为例）。
3. 禁止默认直接 Edit tracked 应用配置文件（如 `application-local-dev.yml`）。
4. 默认启动命令（按技术栈，Java Spring Boot 为例）：
   ```powershell
   powershell.exe -NoProfile -Command "mvn spring-boot:run -pl <module> -Dspring-boot.run.profiles=<profile> -Dspring-boot.run.jvmArguments='-Dspring.config.additional-location=file:C:/temp/harness-execute-overlay/<change-name>/application-harness-execute.yml'"
   ```
5. 写入 `service.pid`、`service-start-command.txt`、`service-start.log`、`runtime/service-session.json`（含 `moduleInputsHash`/`moduleInputsFiles`/`startCommandHash`/`profile`/`overlayPath`/`pid`/`startedBy=AI`/`startedAt`）。`moduleInputsHash` 来自 CLI `--files` ∪ `serviceStart.inputFiles`，空输入拒绝。
6. 服务启动等待：0–30s 每 2s 探测；30–120s 每 5s 探测；>10s 必须输出状态行；>120s 读取最近 200 行日志。
7. 发现启动失败特征（按技术栈识别，如 Java Spring Boot 的 `BindException` / `Could not resolve placeholder` / `Connection refused during bean init` / `BeanCreationException` / `Failed to start bean` / `BUILD FAILURE`）立即失败。

#### 0.10.x 重入沿用（同一变更 harness-execute 再次执行时）

满足以下**全部**条件时，可沿用上次服务决策，不重复询问：

1. 重入：同一 change-name 的 harness-execute 再次执行（非首次）
2. 环境未变：PG 可用性、目标端口、执行器可用性与上次一致
3. 上次已确认执行器方案（如"内存 HTTP 执行器，PG 不可用"）
4. 当前源码未改服务启动逻辑（如未改 main.ts 启动路径、未改服务端口/profile 配置）

沿用时执行日志记录：`重入沿用上次服务决策 + 环境未变（PG=<同上次>、执行器=<同上次>）`。

**不适用重入沿用**（仍须询问/重启）：
- 真实二进制服务需重启（service-fingerprint 不匹配）
- 环境已变（PG 从不可用变可用、端口被占、执行器丢失）
- 上次 serviceState=USER_STARTED（用户手动启动，状态未知）
- 源码改动影响服务启动逻辑

> in-process 内存执行器（无持久服务进程）的重入沿用最常见：PG 不可用→内存 HTTP 执行器方案在环境未变时可沿用，不重复询问服务决策门。

#### 0.11 服务生命周期收尾（即使测试失败也要进入 finally 清理）

测试结束前必须按 serviceState 分支处理：

- `AI_STARTED` → 默认 `Stop-Process -Id <pid> -Force`，删除 `service.pid`，记录 `testServiceStopped=✅`。
- `AI_RESTARTED_FROM_USER_SERVICE` → 默认停止新服务，报告中明确 `restoredOriginalService=❌ not supported`。
- `USER_STARTED` → 保留进程，报告中提示用户可手动停止。
- `REUSED_EXISTING` → 保留进程，除非用户明确要求关闭。

测试报告与 `summary-data.json` 的服务生命周期投影必须包含：

```md
## 服务生命周期
| 项 | 值 |
|---|---|
| originalServicePid | ... / N/A |
| originalServiceStopped | ✅ / ❌ / N/A |
| testServicePid | ... / N/A |
| testServiceStopped | ✅ / ❌ / N/A |
| restoredOriginalService | ❌ not supported / N/A |
| finalPortState | no service / service running |
```

> 不要使用 Monitor 工具等待健康检查，直接用 PowerShell 检查已知接口。通用健康端点（如 Spring Boot 的 `/actuator/health`）可能返回 404。

#### 0.12 服务注册风险确认（如项目适用）

确认应用配置文件中服务注册开关关闭（如 Spring Cloud Nacos 的 `spring.cloud.nacos.discovery.register-enabled: false`），避免线上流量被路由到本地。

## 接口测试执行检查

### 认证凭证缓存与复用

- [ ] 检查 `.harness/changes/<change-name>/runtime/credential-cache.json` 是否存在
- [ ] 如果存在 → 读取已有认证凭证，用**本地轻量接口**（直连本地 baseURL）验证有效性
- [ ] 验证通过 → 复用，不重新登录、不访问远程认证服务
- [ ] 验证失败（401/expired） → 才访问远程认证服务（如 SSO）重新获取后写回 cache
- [ ] 同一上下文中，前面已获取过凭证时必须优先复用
- [ ] **同一次测试流程内只允许因凭证失效重新获取 1 次**；超过 1 次 → 🟡 WARN，记录原因
- [ ] 接口测试执行器用 request context / 原生 HTTP 客户端直连本地 baseURL，**不依赖浏览器当前页面 origin**
- [ ] **不得因浏览器 origin 在远程认证服务就重新获取凭证**；禁止"远程取凭证→导航 localhost→重新取凭证"
- [ ] **不得在报告、execution-log、对话总结中输出明文凭证**

### 单元测试复用（ledger 驱动）

- [ ] Phase 1 前通过 state layout resolver 定位并检查 `evidence/verification-ledger.json`
- [ ] 判断是否复用 run 的 unitTest：diffHash 一致 + module/profile 一致 + scope 一致或更严格 + run 后无行为性修改 + run 实际跑了全量测试
- [ ] 复用 → 跳过重跑，标记"✅ 复用 harness-execute 单元测试结果"
- [ ] 不复用 → 按 profile key resolve 重跑测试命令（`harness_profile.py resolve --key unitTest`，不复制示例 `-pl` 命令），结果写回 ledger 的 `unitTest` 项
- [ ] HTTP/API 契约结果写入 `apiTest`；真实浏览器/真实栈 Playwright 结果写入 `browserTest`，两者不得互相覆盖
- [ ] **本变更没有该维度场景时**（如全部为单元场景 → 无 API 场景）：用 `harness_ledger.py record --verification apiTest --status NOT_RUN --applicability NOT_APPLICABLE --applicability-reason "<为什么不适用>"` 登记，**不传 `--files`**。门禁 close 要求 requiredValidations 每项都有 entry，但**绝不能拿无关文件（比如单元测试文件）凑 `--files`**——那会让 ledger 声称该维度的输入是那些文件，是假证据
- [ ] `can-reuse` 返回 `reuse:false` 时直接读默认输出里的 `reason`/`executionNeed`/`detail` 定位原因，不必再补跑 `--verbose`
- [ ] 复用判断前以 `harness_ledger.py diff-hash --repo . --base <baseCommit> --change-dir ".harness/changes/<change-name>" --json` 重算指纹；test-tracking manifest 无效或 hash 漂移即停止
- [ ] 测试失败若明确为陈旧测试，仅在当前代码/批准计划/可验证历史唯一确定新契约且只改测试时自动修复；否则记录 `BLOCKED_PREEXISTING`
- [ ] 自动修复后立即重跑该测试与目标测试，并以 `harness_test_guard.py record ... --reason stale-test-repair` 记录精确路径
- [ ] **禁止临时排除测试**：未使用 `.bak`/改名/移目录/删除/禁用注解/build exclude/skip-tests 制造通过；服务启动的 `maven.test.skip` 不作为测试证据

### 批量执行器（强制单次 PowerShell + 执行器绝对路径执行）

- [ ] 0.1 preflight 已通过，`preflight.json` 包含 `executorPath`
- [ ] 生成 `.harness/changes/<change-name>/runtime/api-test-runner.mjs`（按技术栈选择实现，Node runner 为一种实现），**按 setup / test / cleanup 三阶段结构**编写
- [ ] payload 来自数据契约 / 接口定义 / 真实样例，执行器注释/JSON 中标注字段来源；**禁止临场猜字段、禁止先跑失败接口再补**
- [ ] 唯一前缀 `TEST_<change-name>_<timestamp>_<random>`，唯一约束字段用随机或避让策略，避免冲突导致 BLOCKED
- [ ] 通过**一次命令**执行（PowerShell + 执行器绝对路径）：
   ```powershell
   powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '<executorPath>' '.harness/changes/<change-name>/runtime/api-test-runner.mjs'"
   ```
- [ ] **禁止**裸 `node ...`、禁止用 Bash 执行 node
- [ ] 执行器失败 ≤ 1 次重试；仍失败 → 提示用户切换权限模式或手动执行，**不得继续盲目重试或长时间等待**
- [ ] 执行器输出 `.harness/changes/<change-name>/runtime/api-test-results.json`，包含
      `passed/failed/blocked/skipped/setupErrors/cleanupResult/credentialRefreshCount`
- [ ] **setup 失败时依赖该数据的场景必须标 🟡 BLOCKED，不得用 null ID 继续请求**
- [ ] 主会话只 Read JSON 生成摘要，不再调用 MCP
- [ ] **只有首选执行器不可执行才降级**：PowerShell batch (.ps1) → 多次 MCP `browser_evaluate` → curl
- [ ] **如果执行器在 PowerShell 可用，禁止使用 Playwright MCP 逐条执行接口测试**
- [ ] 执行器直连本地 baseURL，复用认证凭证，不依赖浏览器 origin
- [ ] 记录每个请求的 requestDurationMs、status、code、message、assertionResult
- [ ] 支持失败时继续执行后续非依赖场景
- [ ] 报告区分四种执行器：**接口测试执行器 / PowerShell batch / Playwright MCP browser_evaluate / curl**（不得与"Playwright"混写）

### 测试数据命名

- [ ] 所有测试数据使用前缀 `TEST_<change-name>_<timestamp>_<random>`
- [ ] 测试报告记录测试数据表（ID、Code、用途、是否需要清理）
- [ ] 测试结束后清理可清理的数据
- [ ] 不能清理的记录遗留数据和原因

### 请求耗时（§5.22 分层耗时）

- [ ] 每个请求记录 requestDurationMs（单 HTTP 请求耗时）
- [ ] 整个批次记录 batchDurationMs（runner wall-clock）
- [ ] requestDurationMs > 10000 → 🟡SLOW，说明原因
- [ ] requestDurationMs > 30000 → ❌TIMEOUT_RISK，说明原因
- [ ] batchDurationMs > 180000 → 🟡BATCH_SLOW
- [ ] 聚合合同套件场景只记录 batch reference + coveredTests，**禁止均摊生成伪 requestDurationMs**

### 覆盖标注诚实性（✅ 实测 vs 🟡 推断）

场景状态标注规则：

- [ ] ✅ 仅当断言实际执行**且**场景声明的前置条件/数据真实构造
- [ ] 🟡（推断）：未构造场景条件、以相邻场景或同接口行为推断时使用，必须注明推断依据
- [ ] 用同一请求重复调用来"覆盖"不同异常场景 → 一律 🟡
- [ ] 报告汇总行的通过数只统计 ✅（不含 🟡 推断）

## 关门检查（⚠️ 结束前强制执行）

- [ ] `powershell.exe -NoProfile -Command "git status --porcelain"`
- [ ] `powershell.exe -NoProfile -Command "git diff --stat"`
- [ ] `powershell.exe -NoProfile -Command "git diff --check"`（如果失败 → 最终结果 ❌FAIL）
- [ ] 检查报告和日志是否包含明文凭证/password/secret/access-key/client-secret
- [ ] 检查 `.harness/changes/<change>/runtime/` 是否不会被提交（.gitignore 确认）
- [ ] **服务生命周期收尾**：AI_STARTED→Stop-Process / USER_STARTED→提示 / REUSED_EXISTING→保留或确认 / NOT_STARTED→N/A
- [ ] **资源生命周期收尾**：Runner 单实例锁已释放，测试进程树无新增残留，未对用户原有 Python/Node 进程做宽泛清理
- [ ] 检查测试数据是否需要清理
- [ ] 检查请求执行器结果是否完整（4 种执行器，未与接口测试执行器混写）
- [ ] 检查是否存在慢请求或超时风险
- [ ] **API 维度状态正确**：5 PASS + 9 BLOCKED + 1 FAIL → `apiTest=PARTIAL`，不得写成 `NOT_RUN`
- [ ] 如果存在未清理测试数据、fallback 请求执行器、慢请求或环境变更 → 至少 🟡WARN

## 关键原则

- 如果有项目配置文件，优先从 `.harness/config/harness-test-config.md` 读取并应用（含已知良好测试配置）
- 环境准备（阶段 0）的 **命令执行模式 preflight + 各项环境检查 + fallback 执行器探测** 必须在测试之前全部通过
- 单元测试优先于接口测试（先跑测试命令，通过后再跑接口）
- 接口测试优先级：**接口测试执行器 > PowerShell batch > Playwright MCP browser_evaluate > curl**
- 单用例失败不阻塞后续用例；setup 失败时依赖场景必须标 🟡 BLOCKED，**不得用 null ID 继续请求**
- 失败类型必须区分：代码 Bug vs 测试脚本问题 vs 预存问题
- 测试数据使用唯一前缀命名 + 唯一约束字段随机或避让，测试后确认清理或记录遗留
- 测试报告持久化到 `.harness/changes/<change-name>/reports/test/test-report-YYYYMMDD-HHmm.md`（时间戳区分多次运行）
- 请求执行器必须在报告中明确记录（四种执行器，含降级原因）
- 请求耗时统计必须包含在报告中
- 服务由 AI 启动的情况，测试结束默认 Stop-Process；**即使测试失败也要进入 finally 清理**
- `summary-data.json` 与平台监控中的 `apiTest` 状态必须使用 OK/PARTIAL/BLOCKED/NOT_RUN/FAIL（不得把 PARTIAL 写成 NOT_RUN）
