# tester 目录字段 术语与命名理由见 [concepts.md](concepts.md);本文件只列字段与约束。 项目根 `.pouch/tester/`: ``` catalog.yaml 分类、风险阶梯、session、变量、默认 Agent 目标 local.yaml.example HOST、授权开关和 Agent 目标模板(默认 127.0.0.1) local.yaml 本机覆盖,不提交 cases/.yaml 一个分类一个文件(执行源) cases.csv 给人看的扁平清单;只由 cases/*.yaml 生成,不包含运行结果 runs/.yaml 每次运行快照(执行源);run-id 必须唯一 runs/*.csv 同一次运行的成绩单;generate_run_csv.py 从对应 yaml 生成 ``` ## catalog.yaml | 字段 | 含义 | |------|------| | `categories` | `{id, title, status_probe?}` 列表,id 与 `cases/.yaml` 对应;列表顺序即 `select` / 执行顺序。`status_probe` 见下 | | `risks` | 从低到高,只能是 `readonly` → `mutating` → `destructive` 的一段,且以 `readonly` 开头。含义见 [levels.md](levels.md) | | `default_max_risk` | 未指定时的运行上限,必须是 `risks` 里的值 | | `vars` | 可替换变量,如 `API_BASE: http://${HOST}:8095` | | `artifacts` | 可选的移动产物身份契约。按 `android` / `ios` 声明 `required` 和 `package` / `bundle_id`;每轮文件路径或下载地址由调用方提供,不提交临时产物路径。 | | `authorize` | 风险名 → 环境变量名。该档执行前变量必须为 `true`(`readonly` 不需要) | | `gates` | 可选。项目细分闸名 → 环境变量。用在用例的 `gate` 上,不要拿它代替 `risk` | | `sessions` | 可复用会话。`kind`: `browser` / `mobile`;`reuse`: `run`(本轮结束关掉)或 `persist`(probe 活着就附着) | | `id_pattern` | 用例 id 正则 | | `run_together` | 可选。成组执行:`[{ids: [TC-…, TC-…], continue_on_fail: true}]`。点到组内任一条,`select` 会按 `ids` 顺序把整组扩进命中列表。`continue_on_fail: true` 时组内前一条产品 fail 仍跑后一条(返回/收尾)。一个 id 只能属于一组。 | | `status_probe` | 可选。顶层默认值,一个**分类级前置条件**:`{url, stop_if: {字段: [命中值]}}`。运行前请求 `url`,响应命中任一 `stop_if` 条件即视为前置不满足。分类项可用同名键覆盖:缺省继承顶层、`false` 关闭、mapping 整体替换。命中或不可达只影响用它的分类,不是产品失败。业界对应 pytest 的 session fixture / Robot 的 Suite Setup。`select` 会按分类返回解析后的生效值,`url` 已用 `vars` 展开 | `local.yaml` 与环境变量覆盖 `HOST` 和授权开关。模板中的 `HOST` 默认是 `127.0.0.1`;远程目标必须显式覆盖。查找顺序:环境变量 > `local.yaml` > `catalog.yaml` 的 vars。也认 `HX_TEST_HOST` 作为 `HOST`。 ## agent `catalog.yaml.agent` 是可提交的默认 Agent 目标,`local.yaml.agent` 对其做浅层覆盖。 它不参与 `HOST` 变量解析,也不会把远程机器路径写入环境变量。机器路径和临时 Agent 选择优先写在不提交的 `local.yaml`。 | 字段 | 含义 | |------|------| | `environment` | Orca 保存的远程环境选择器;空值使用当前环境 | | `host` | 目标机器标识,默认 `local` | | `project` | Orca project id 或名称;也可由 terminal id 自动解析 | | `path` | 目标机器上的项目路径;空值表示当前项目根目录 | | `role` | Agent 角色,tester 固定为 `test` | | `cli` | `codex` / `cursor-agent` / `grok` / `omp` / `pi` | | `tier` | `standard` / `strong` | | `model` | 精确模型 ID;`null` 表示使用 CLI 默认模型 | | `reasoningEffort` | `low` / `medium` / `high` / `xhigh` 或 `null` | | `permissionMode` | `read-only` / `workspace-write` | 用户给 project id、项目名称或 terminal id 时,tester 先解析并写入 `local.yaml.agent`, 再展示更新后的 Agent/环境/项目/目录生效列表。每轮创建新 terminal,不复用既有 terminal;运行结束用 `orca terminal close --terminal ` 关闭本轮创建的 terminal。 运行快照保存解析后的 Agent、目标、worktree 和 terminal handle。旧版 `execution` 字段 只作为兼容输入读取,不再作为新配置写出。详见 [execution.md](execution.md)。 运行记录使用 UTC 时间加随机后缀命名,例如 `20260920T101530Z-smoke-a13f9c.yaml`,并在 YAML 顶层保存同一个 `runId`。 不要使用固定的 `latest.yaml` 或覆盖已有运行文件。 ## 一条用例 写在对应分类文件的 `cases:` 列表里。 | 字段 | 必填 | 含义 | |------|------|------| | `id` | 是 | 匹配 `id_pattern` | | `category` | 是 | 必须等于文件声明的 category | | `title` | 是 | 短名 | | `what` | 是 | 一句可观察的「测什么」 | | `lifecycle` | 是 | `active` / `pending` / `retired`。`pending` = 暂缓,仍保留在目录里但不执行,原因写在 `notes` | | `tag` | 是 | `smoke` / `full` / `slow`,判定见 [levels.md](levels.md)。`tag=smoke` 只能配 `risk=readonly` | | `risk` | 是 | `readonly` / `mutating` / `destructive` | | `gate` | 否 | 项目细分闸,必须在 catalog `gates` 里;`risk=readonly` 不要填 | | `driver` | 否 | `script` / `browser` / `mobile`;`automation=manual` 时禁止填 | | `automation` | 否 | `automated`(默认)/ `assisted` / `manual`,见 [concepts.md](concepts.md) | | `session` | browser/mobile 必填 | 指向 catalog `sessions` 的键 | | `how` | 是 | 怎么测,见下 | | `expected` | 是 | 怎么过,至少一条 `{kind, value}` | | `maps_to` | 否 | 对人文档的功能项 id | | `assume` | 否 | 额外跳过条件(环境变量表达式)。不要重复 `risk` / `gate` 已覆盖的授权变量,否则 `validate` 报错 | | `setup` | 否 | 人话前置 | | `teardown` | 否 | 跑完回退 | | `notes` | 否 | 备注 | ## how 按 `driver` 分派;`automation=manual` 时没有 `driver`,只有 `how.steps`(人工步骤)。 - `script`:`how.run` 是一条可在项目根执行的命令(可多行脚本)。没有 `run` 时 Agent 按 `how.steps` 做,仍不得发明未写明的请求。 - `browser`:`how.url` + `how.steps`。`expected.kind` 用 `visible-text` / `url` / `interaction`。 - `mobile`:`how.steps`,挂到 `session` 指定的模拟器。`expected` 同样是可观察信号。 可选 `how.timeout`,秒,默认 60。 `automation=assisted` 时,至少一个 `how.steps` 条目要以 `[人工]` 开头(写在 YAML 里要加引号,`[` 开头会被当成流式序列)。 ## expected.kind `api-status` / `api-field` / `script-exit` / `visible-text` / `url` / `interaction` ## 判定 `pass` / `fail` / `environment-fail` / `skipped` / `not-run`