Chrome 扩展 Demo 的 fixture、--no-auto-env 参数传递、修复后重建和批次隔离按 ${CLAUDE_PLUGIN_ROOT}/protocols/web-demo-run-repair-contract.md 的“扩展 Demo 运行模式”;仅此模式下不执行默认 Web 环境 stop/start。
批量运行 Demo 测试(主会话逐文件驱动)
运行时边界:${CLAUDE_PLUGIN_ROOT}/protocols/runtime-boundaries.md(判断脚本入口或项目事实与插件默认冲突时读)
单文件运行与修复闭环:${CLAUDE_PLUGIN_ROOT}/protocols/web-demo-run-repair-contract.md(处理任一失败文件前读)
目标
- 自动发现除
live/、fixtures/、templates/、verification/和文件名含test-之外的全部 Demo 测试(发现规则脚本内固化,不在 skill 层重写)。 - 由当前主会话逐个文件驱动,每一步都是可观察、可中断的短 Bash / Agent 调用。
- 单文件失败时按
web-demo-run-repair-contract.md的修复闭环处理,每文件最多 6 次尝试。 - 文件之间重建 Demo 环境和数据容器,避免前一文件产生的业务数据影响后续测试。
- 每文件达到上限仍失败则标记
FAILED并继续下一个文件,不阻塞整批。 - 持续写盘批次状态,支持
continue从未完成文件的断点恢复;产出 Markdown + JSON 汇总报告。
两种模式
默认逐文件模式(无参数 / continue):发现 → 逐文件跑 → 失败就当场修复 → 文件间数据隔离 → 收尾。每个文件独立诊断修复,互不参照。
扫描模式(scan):先纯 Bash 预跑全部文件不修复,按归一化错误指纹聚类失败,再对每个 unique cluster 只修一次(用 representative 文件),最后回扫所有受影响文件。
何时用扫描模式:失败密集且疑似共享根因(如一批文件都挂在同一个失效 selector 或同一个后端接口变更上)。先用 ${CLAUDE_PLUGIN_ROOT}/guides/web-demo/batch-token-profiling.md 的决策树判断;孤立失败为主或文件数少(< 5)时用默认模式,扫描模式的聚类开销不划算。不确定时先跑默认模式一次,再用该指南读画像决定。
执行流程(默认逐文件模式)
A. 发现阶段(一次性,脚本辅助)
uv run scripts/web-demo-run-all.py discover [--filter-file <path>] # fresh
uv run scripts/web-demo-run-all.py discover continue # 断点恢复
stdout 打印单行 JSON,必须解析它,后续循环使用其中的 discovered_files(仓库相对路径列表)、batch_run_id、json_report(批次产物路径)和 resume_index(fresh 为 0)等字段,字段语义以脚本输出为准。脚本同时已写好初始批次 JSON(fresh)或已截断/重置好状态(continue)。脚本返回非零时按其错误信息处理(如 continue 找不到可继续内容则终止)。
B. 主循环:对 discovered_files[resume_index:] 逐个文件
对每个文件记其 zero_based_index(在 discovered_files 中的全量下标,不是切片下标),依次执行:
B1. 写断点
uv run scripts/web-demo-run-all.py checkpoint --json <json_report> --index <zero_based_index>
B2. 运行整个测试文件
uv run scripts/web-demo-test-runner.py "<rel_path>" --run-id "<batch_run_id>-<file_key>-initial" --mode fast
web-demo-test-runner.py 会自检并按需启动/恢复 demo 环境。解析其最后一行 Result: {...},按 web-demo-run-repair-contract.md 的 Runner 输出适配映射为 snake_case 批次 entry 字段。file_key 必须由相对路径的稳定 slug 或短哈希生成,避免不同目录的同名文件冲突。
B3. 整文件通过
success == "true":本文件标记 passed、fixed=false,跳到 B5。
B4. 整文件失败 → 执行共享修复闭环
按 web-demo-run-repair-contract.md 的单文件执行顺序和修复行为处理当前失败用例,最多 6 轮。终验通过才记 status=passed, fixed=true;达到上限仍失败时记 status=failed, fixed=false,保留最后失败证据并继续批次。
B5. 持久化 + 文件间数据隔离
保留最小结果:只保留
{status, exit_code, duration, run_id, logs, fixed};仅失败时再保留一句简短error。文件名、下标、计数和总耗时由脚本推导。数据隔离:若还有下一个文件,无论当前文件成功或失败,均按共享修复协议选择隔离方式。独立扩展模式确认 fixture 已清理 profile/stub;默认 Web 模式重建 Demo 环境和数据容器。隔离失败时执行
block后中止批次(该命令保留断点且不追加结果)。以下 stop/start 仅用于默认 Web 模式:uv run scripts/demo-stop.py --quiet && uv run scripts/demo-start.py uv run scripts/web-demo-run-all.py block --json <json_report> --error "<简短原因>"写结果并推进断点:数据隔离成功,或当前已是最后一个文件时,执行一条短命令。
record自动补齐test_file,更新断点、计数和总耗时;成功结果不传--error:uv run scripts/web-demo-run-all.py record --json <json_report> --status <passed|failed> --exit-code <n> --duration <s> --run-id <id> --logs <path> [--fixed] [--error "<失败摘要>"]
B6. 进入下一个文件
主会话进度只输出一行,不复述诊断、命令或 JSON:
[<完成数>/<总数>] <PASS|FIXED|FAIL> <test_file> (<duration>s)
仅在 FAIL 或批次阻塞时追加一句原因;run ID、日志路径和累计统计留在最终报告中。
C. 收尾
所有文件处理完(或切片耗尽)后:
uv run scripts/web-demo-run-all.py finalize --json <json_report>
脚本渲染 Markdown 报告并置 batch_status=completed,在 stdout 打印 Passed: N Failed: M;failed_count == 0 时返回 0,否则返回 1。失败文件的诊断报告已在 B4 内联生成,批次结束后不再单独批量跑 web-demo-diagnose。
恢复机制
中断(手动 Ctrl-C、会话结束、上下文压缩)后:
/t-tools:t-web-demo-run-all continue
discover continue只恢复最近且batch_status=running的批次:存在current_file时从该文件重跑,否则从current_index(必须等于已持久化 entry 数)继续。已持久化的成功或失败文件都不重跑。- 无可继续内容时脚本返回非零并提示,skill 终止。
- 恢复点总是某个尚未写最终 entry 的文件;从 B1 重跑该文件并重建当次修复上下文。
批次状态契约
批次 JSON 由 web-demo-run-all.py 维护(batch_status / discovered_files / entries[] / current_file / last_error 等派生字段见脚本实现)。主会话不得读取、展开或整份重写 JSON,只通过 discover / checkpoint / record / block / finalize 子命令推进状态。
执行流程(扫描模式)
扫描模式把"先看全貌、再按唯一根因修"作为前置阶段,复用同一份批次 JSON 的 scan_results 字段。scan/cluster 子命令在 ${CLAUDE_PLUGIN_ROOT}/scripts/web-demo-run-all.py 中定义。
S1. 发现阶段
同默认模式的 A 阶段(discover [continue])。
S2. 预扫描(纯 Bash 驱动,禁止 subagent)
uv run scripts/web-demo-run-all.py scan --json <json_report> [--scan-run-id <id>]
为每个 discovered_files 条目建一条 pending 记录(幂等:已存在 scan_results 且未 --force 时直接返回当前进度)。逐文件跑 fast 模式,不进修复闭环(runner 调用与结果登记同默认模式 B2 的参数映射,run-id 用 <scan_run_id>-<file_key>-scan):
uv run scripts/web-demo-test-runner.py "<rel_path>" --run-id "<scan_run_id>-<file_key>-scan" --mode fast
uv run scripts/web-demo-run-all.py scan --json <json_report> --file <rel_path> --status <passed|failed> --exit-code <n> --duration <s> --run-id <id> --logs <path>
约束:此阶段禁止 dispatch subagent;文件间数据隔离同默认模式 B5;每文件只输出一行进度。
S3. 聚类(纯 Python,无 subagent)
uv run scripts/web-demo-run-all.py cluster --json <json_report>
读取 scan_results 里所有 failed 条目,从各自 run_id 指向的 playwright-output.log 提取失败用例,按归一化错误指纹聚成 clusters。stdout 单行 JSON 含 clusters[](每项 {fingerprint, representative_error, affected_files[], affected_cases[]},按受影响文件数降序)和 unclusterable[](缺 run_id / 日志丢失 / 无可解析失败的条目,不得静默丢弃,需逐条人工处理或回退默认模式单文件修)。
S4. 逐 cluster 修复(此阶段才用 subagent)
对 clusters[] 按受影响文件数降序逐个处理:
- 选 representative:取该 cluster 的
affected_files[0]与affected_cases[0]。 - 修复闭环:按
web-demo-run-repair-contract.md对 representative 执行完整单文件闭环(最多 6 轮,超限标该 cluster 失败并继续下一个 cluster)。 - 回扫受影响文件:representative 修复后,对该 cluster 所有
affected_files重跑 fast 模式(复用 S2 的 runner +scan --file登记,run_id 用<scan_run_id>-<file_key>-verify)。全部通过则这些文件标passed, fixed=true;仍有失败则该文件存在独立根因,回退默认模式对该文件单独走修复闭环。回扫同样遵守文件间数据隔离。
S5. 收尾
同默认模式的 C 阶段(finalize)。失败 cluster 的诊断报告已在 S4 内联生成,批次结束后不再单独批量跑 web-demo-diagnose。
finalize读取entries[];扫描模式逐文件结果落在scan_results。收尾前需把scan_results的最终状态映射为entries,或直接以scan_results为准产出报告。两字段语义平行,不得相互覆盖。
质量门禁
- 由主会话直接驱动循环;禁止 fork 嵌套
claude -p或任何把整批吞进单一长阻塞 Bash 调用的写法。 - 不允许并行执行多个测试文件,不允许使用 slow/headed 模式。
- 所有
Agent调用必须先按subagent-dispatch.md注入角色规范。 - 必须以
finalize收尾产出报告;不得由主会话覆盖整份 JSON。 - 单文件修复闭环以
web-demo-run-repair-contract.md为唯一契约源,本 skill 只编排批次状态、文件间隔离和汇总。
失败处理
discover找不到文件或continue无可继续内容:终止并给出脚本返回的错误。- 后端代码变动后的验证前重建失败:记录本轮失败,不在旧后端进程上验证。
- 文件间数据隔离失败:记入
last_error并中断批次,由continue恢复。 - runner 启动失败:按整文件失败处理,记录错误并继续。