frontend-explorer · v0.1.0 · 2026-09-10 · sha256 1e8c9e8e76e2d97b
frontend-explorer v0.1.0A
Immutable. This exact content is served forever at /api/v1/blob/1e8c9e8e76e2d97b.
--- name: frontend-explorer version: 0.1.0 description: 探索型前端测试——派一个「第一次见这个产品」的探索者,用 playwright-cli 驱真浏览器走完一段旅程,回一份按挡路程度排序的「在哪卡住 / 哪里看不懂」清单,每条带屏幕原文与截图证据。触发:探索一遍 / 走一遍 / 踢踢轮胎 / UX pass / 找新用户会在哪迷路。不用于判据已知的验收探针、回归测试、性能、代码评审。 --- # frontend-explorer — 探索型前端测试 脚本化测试回答「我已经想到的那件事还好使吗」。这里回答另一个问题:**一个从没见过这个产品的人 打开它——在哪停住,在哪盯着屏幕不明白?** 这两种失败形态就是全部产出;其余一切只为让这份产出诚实。 本 skill 对你的项目一无所知:应用在哪跑、怎么拿登录态、屏幕上的词什么意思,全部来自一份配置 (`references/config.example.yaml`)。想改本 skill 的文件去适配项目 = 那个事实该进配置。 ## 前置条件 1. **一份配置**:复制 `references/config.example.yaml` 填好;含本机路径就别进版本库。做任何事之前先读它。 2. **应用在跑且可达**:`base_url` 可访问、其 host 在 `allowed_origins` 里。没在跑就按配置 `auth.setup` 起, 不要自己发明启动方式。 3. **浏览器驱动 = `playwright-cli`**(`@playwright/cli`,0.x 命令面会漂,项目钉版本):探索者经 Bash 调它, 每个 persona 一个命名会话 `-s=<persona.session>`,与项目自己的会话及彼此天然隔离、可并行。不用 Playwright MCP、 不用别的驱动、不调外部 LLM API。工具选型与登录态原则与 cto-orchestration `references/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 门**——接了只会教所有人忽略它。 ## 接入与移植(三处改动) 1. **写配置**:复制 `references/config.example.yaml` 填好。这是唯一要编辑的文件;`journey` 与 `glossary` 写对,其余机械。glossary 是本次能发现什么的**天花板**——写进去的每个词都是探索者被禁止困惑的词, 只放真新用户确实被告知的。 2. **落一个 hold 用例**:把 `references/hold-spec.template.ts` 拷进项目 e2e 目录,指向项目已有的 「拿到已登录页面」的办法(通常两行);从必跑测试里排除它(无断言、不自行终止)。`auth.setup.command` 指向它。应用已在跑且已有 state 文件 → 跳过,`auth.mode: storage_state`。 3. **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 用例模板。