frontend-explorer — 探索型前端测试
脚本化测试回答「我已经想到的那件事还好使吗」。这里回答另一个问题:一个从没见过这个产品的人 打开它——在哪停住,在哪盯着屏幕不明白? 这两种失败形态就是全部产出;其余一切只为让这份产出诚实。
本 skill 对你的项目一无所知:应用在哪跑、怎么拿登录态、屏幕上的词什么意思,全部来自一份配置
(references/config.example.yaml)。想改本 skill 的文件去适配项目 = 那个事实该进配置。
前置条件
- 一份配置:复制
references/config.example.yaml填好;含本机路径就别进版本库。做任何事之前先读它。 - 应用在跑且可达:
base_url可访问、其 host 在allowed_origins里。没在跑就按配置auth.setup起, 不要自己发明启动方式。 - 浏览器驱动 =
playwright-cli(@playwright/cli,0.x 命令面会漂,项目钉版本):探索者经 Bash 调它, 每个 persona 一个命名会话-s=<persona.session>,与项目自己的会话及彼此天然隔离、可并行。不用 Playwright MCP、 不用别的驱动、不调外部 LLM API。工具选型与登录态原则与 cto-orchestrationreferences/frontend-verify.md同向(可选阅读,非依赖)。
流程(五步)
1 — 准备会话。 配置有 auth.setup.command 就跑它:它负责把应用带起来、签一个新用户、写出
auth.session_file(含入口 URL 与 storageState 路径),并停在前台。
2 — 派发前先冒烟。 对每个 persona 的会话起浏览器、载入登录态、亲眼确认:
playwright-cli -s=<会话> open <entry_url>
playwright-cli -s=<会话> state-load <storageState 文件>
playwright-cli -s=<会话> goto <entry_url>
playwright-cli -s=<会话> find "<signed_in_marker.visible_text>"
看到标记文本才算登录态生效。没亲眼看到会话有效就派探索者 = 它报的每条 finding 都是「没登录」的伪影。
登录态只经文件路径进浏览器(state-load)。禁止 cookie-set / cookie-get / cookie-list / localstorage-* / sessionstorage-*,禁止在 eval 正文里碰 cookie / token / localStorage——值上了命令行
或 stdout 就进了 transcript——一次性 session token 正是这样泄漏的。state-save 只许落
gitignored 的输出目录。
3 — 派发探索者。 配置里每个 persona 派一个独立子代理,brief 按 references/dispatch.md 组装,
自包含——子代理看不到本对话。席位形态:带 Bash 的子代理(Agent 工具)或 agentctl start claude
完整席位;cwd 设为输出目录、或独立 worktree 兜只读。探索者只读:驱动浏览器、只往 output.dir
写文件;不读不改不跑项目代码,不离开 allowed_origins。
4 — 筛选。 对原始产出按 references/triage.md 自己筛,在编排上下文里做——噪声在这里死掉;
别交回产出它的那个代理(作者是最差的裁判)。
5 — 产出。 findings.json(按 references/output-schema.json 校验)与 findings.md 落 output.dir。
两轮法(产量几乎全在第二轮)
第一轮走通路(happy path),抓的多是命名与渲染不一致;第二轮专攻返工、失败、权限切换—— 用户真正会撞的都在这里,机制测试结构上够不着。两轮 = 两个 persona:配置示例内置「首访者」与 「做错了怎么办」,各项目只改词,不必每次手写第二轮 brief。
输出契约(硬)
每条 finding 三格,缺任一格即删除、不补:
| 格 | 含义 |
|---|---|
step |
旅程的哪一步,取自配置 journey 的 id |
kind |
blocked(走不下去)或 confused(走下去了但不明白) |
evidence |
URL、屏幕原文逐字、截图路径 |
- 只报真撞上的。 没有「可以改进」「要是…更好」「用户可能」;探索者没在浏览器里撞到的不存在。
- 最多 10 条,按挡住旅程的程度排序。
- finding 是观察不是工单:写发生了什么,不写该做什么。
steps_not_reached(没走到的步)与筛选掉落表必报——不自报边界的探索报告不可消费。
护栏
- 永远只读。探索者没有修任何东西的授权。
- 导航围栏 =
allowed_origins:离开围栏的链接本身可报,但不跟。 - 截图会拍到凭证、邀请码、个人数据。遵守配置
redact表:屏幕值命中就不截那块,引用旁边的标签并注明值已隐去。 - 产物天然非确定。永不接进 CI 门——接了只会教所有人忽略它。
接入与移植(三处改动)
- 写配置:复制
references/config.example.yaml填好。这是唯一要编辑的文件;journey与glossary写对,其余机械。glossary 是本次能发现什么的天花板——写进去的每个词都是探索者被禁止困惑的词, 只放真新用户确实被告知的。 - 落一个 hold 用例:把
references/hold-spec.template.ts拷进项目 e2e 目录,指向项目已有的 「拿到已登录页面」的办法(通常两行);从必跑测试里排除它(无断言、不自行终止)。auth.setup.command指向它。应用已在跑且已有 state 文件 → 跳过,auth.mode: storage_state。 - gitignore 输出目录:
output.dir一行。findings、截图、session 文件都落那里,都不该进仓库。
安装:ln -s <evolab>/skills/frontend-explorer ~/.claude/skills/frontend-explorer(或整目录复制)。
除 playwright-cli 外零依赖。
不做的事
不做门禁;不提修法(观察归它,决定归人);不碰你的代码。
References
references/dispatch.md— 子代理 brief 模板。references/persona.md— 探索者是谁、什么算 finding。references/triage.md— 原始笔记到可执行清单之间的过滤器。references/output-schema.json— JSON 契约。references/config.example.yaml— 全部项目旋钮(填好的通用示例)。references/hold-spec.template.ts— 让已登录栈活到 pass 结束的 Playwright 用例模板。