关于 resilience-review
resilience-review 是用于检查 Web 应用故障处理与边缘情况的评审技能,适合上线前检查或可靠性改进。它通过浏览器故障注入收集证据,并提供修复建议和 YAML 回归测试。
主要功能
- 01梳理 API 调用、依赖和关键流程
- 02检查错误、降级状态与边缘情况
- 03注入浏览器故障并记录证据
- 04报告用户影响和置信度
- 05提供修复建议与 YAML 回归测试
适用场景
- 01在功能上线前检查故障处理
- 02调查生产事故后的可靠性问题
- 03测试新的 API 集成和数据源
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ shiplightai/ agent-skills --skill resilience-review安装后在 Claude Code 中输入/resilience-review确认已加载。
详细介绍
弹性审查
评估应用在出现故障时的表现,例如网络中断、API 错误、连接缓慢、数据缺失和边界情况。大多数应用都是围绕理想情况构建的;本审查会系统地测试真实用户会遇到的各种异常情况。
适用场景
在以下情况下使用 /resilience-review:
- 面向用户的功能上线前
- 添加新的 API 集成或数据源后
- 可靠性至关重要时(医疗保健、金融、电商结账)
- 发生因未处理错误导致的生产事故后
- 从原型转向生产级质量时
参考标准
- Google SRE Principles — 错误预算、优雅降级
- Netflix Chaos Engineering Principles — 验证稳态、注入现实世界的故障
- OWASP Error Handling — 安全且对用户友好的错误响应
- Nielsen Norman Group — 错误消息可用性启发式原则
阶段概览
Phase 1: EDUCATE → Why resilience matters and what we test
Phase 2: SCOPE → Map failure points, dependencies, critical flows
Phase 3: ANALYZE → Browser-based fault injection and edge case testing
Phase 4: REPORT → Findings with evidence and user impact assessment
Phase 5: REMEDIATE → Fix guidance + YAML regression tests
阶段 1:说明
为何重要: 用户不会总是在理想条件下使用应用。如果页面加载时间超过 3 秒,53% 的移动端访问会被放弃。缺少指引的错误页面会使支持工单增加 5 倍。空白屏幕是最糟糕的故障模式——它没有向用户提供任何信息,也没有提供恢复途径。即使后端系统发生故障,弹性良好的应用也能维系用户信任。
本审查会在浏览器中模拟现实世界的故障条件,并评估 UI 的响应方式。
阶段 2:确定范围
收集上下文
-
从代码库自动检测:
- API 调用及其端点
- 错误边界组件(React ErrorBoundary、Vue errorHandler)
- 加载状态实现(加载指示器、骨架屏、suspense)
- 空状态组件
- 重试逻辑/错误恢复模式
- 离线支持(service worker、缓存策略)
- 第三方服务依赖项
-
询问用户(每次询问一个问题):
- 目标 URL:应用运行在哪里?
- 关键用户流程:哪些流程绝不能显示空白屏幕?(根据路由自动检测)
- 关键 API 依赖项:前端依赖哪些 API?(自动检测)
- 已知脆弱区域:是否有经常出问题的页面/功能?(可选)
-
梳理故障点:
- 前端调用的 API 端点(以及每个端点故障时的处理方式)
- 第三方依赖项(CDN、身份验证提供商、分析、地图、支付)
- 依赖数据的 UI(数据为空、缺失或格式错误时的显示内容)
- 用户输入边界情况(长文本、特殊字符、空提交)
阶段 3:分析
使用 new_session 打开浏览器会话,并设置 record_evidence: true。运行所有适用的检查类别。
类别 A:错误处理(ERR)
| 检查 ID | 检查项 | 标准 | 方法 |
|---|---|---|---|
| ERR-01 | API 错误会显示对用户友好的消息(而非空白屏幕) | UX 最佳实践 | 模拟 API 返回 500,检查 UI 响应 |
| ERR-02 | 网络超时会显示适当的状态 | UX 最佳实践 | 模拟网络延迟(30s),检查 UI |
| ERR-03 | 404 页面存在且有帮助 | UX 最佳实践 | 导航至不存在的路由 |
| ERR-04 | JavaScript 错误不会导致页面崩溃 | 错误边界 | 注入 JS 错误,检查页面是否恢复 |
| ERR-05 | 错误消息具有可操作性 | NN/g 启发式原则 | 检查错误消息是否说明:发生了什么、原因是什么、该怎么做 |
| ERR-06 | 错误不会暴露技术细节 | OWASP | 检查错误消息中是否包含堆栈跟踪、SQL、内部路径 |
| ERR-07 | 表单验证错误清晰且位置恰当 | UX 最佳实践 | 提交无效表单,检查错误的位置和文本 |
| ERR-08 | 错误状态下无需刷新页面即可重试 | UX 最佳实践 | 发生错误后,检查是否有重试按钮或恢复操作 |
| ERR-09 | 并发错误处理(多个同时发生的故障) | 弹性 | 模拟多个 API 故障,检查 UI 是否会连锁出错 |
| ERR-10 | 错误日志不会暴露 PII | OWASP / 隐私 | 在发生错误时检查 get_browser_console_logs |
浏览器验证: 使用 description: + js: 语句通过 page.route() 拦截网络请求,以模拟故障。检查每次故障后的 UI 状态。使用 get_browser_console_logs 检查 JavaScript 错误。
// Example: Mock API 500 error
await page.route('**/api/**', route => {
route.fulfill({ status: 500, body: JSON.stringify({ error: 'Internal Server Error' }) });
});
类别 B:优雅降级(DEG)
| 检查 ID | 检查项 | 标准 | 方法 |
|---|---|---|---|
| DEG-01 | 禁用 JavaScript 时页面仍可正常使用(基本内容) | 渐进增强 | 禁用 JS,检查内容是否可访问 |
| DEG-02 | 慢速网络连接下页面仍可正常使用(模拟 3G) | 性能 | 限速至 Slow 3G,检查加载行为 |
| DEG-03 | 非关键功能降级时不会影响关键功能 | 优雅降级 | 禁用第三方脚本,检查核心功能 |
| DEG-04 | 能处理离线状态(如适用) | PWA 最佳实践 | 切换为离线,检查 UI 状态和提示信息 |
| DEG-05 | 第三方服务故障不会阻止页面加载 | 弹性 | 屏蔽第三方域名,检查页面是否加载 |
| DEG-06 | 图片加载失败时显示备用内容 | UX 最佳实践 | 屏蔽图片 URL,检查是否显示替代文本/占位符 |
| DEG-07 | 字体加载失败时不会隐藏文本 | FOUT 处理 | 屏蔽字体 URL,检查文本是否仍然可见 |
| DEG-08 | 优先采用功能检测,而非浏览器嗅探 | 渐进增强 | 检查代码使用的是 navigator.userAgent 还是功能检测 |
浏览器验证: 使用 page.route() 屏蔽特定资源。使用 CDP 模拟网络状况。通过浏览器设置禁用 JavaScript。验证每种降级场景。
类别 C:空状态和边界情况(EDGE)
| 检查 ID | 检查项 | 标准 | 方法 |
|---|---|---|---|
| EDGE-01 | 空数据状态显示有帮助的信息 | UX 最佳实践 | 导航到没有数据的页面,检查显示内容 |
| EDGE-02 | 分页正确处理零结果 | UX 最佳实践 | 搜索不存在的词条,检查分页 |
| EDGE-03 | 长文本不会破坏布局 | 防御性 CSS | 输入非常长的字符串(500+ 个字符),检查溢出 |
| EDGE-04 | 输入中的特殊字符不会破坏 UI | 输入处理 | 输入 <script>、"'&<>、表情符号、Unicode |
| EDGE-05 | 大型数据集不会导致 UI 卡死 | 性能 | 加载数据量最大的页面,检查响应情况 |
| EDGE-06 | 用户快速操作不会导致重复提交 | 状态管理 | 双击提交按钮,快速导航 |
| EDGE-07 | 前进/后退导航会保留状态 | 历史记录管理 | 填写表单,离开页面后再返回 |
| EDGE-08 | 刷新后会保留预期状态 | 状态持久化 | 在多步骤流程中刷新,检查状态 |
| EDGE-09 | 并发标签页/会话行为 | 会话管理 | 在两个标签页中打开同一页面并执行操作 |
| EDGE-10 | 正确处理最大文件上传大小 | 输入验证 | 上传超大文件,检查错误消息 |
**浏览器验证:**导航到各个页面并测试每种边界情况。使用 act 与表单交互,并提交空数据或极端数据。使用 JavaScript 检查 UI 是否溢出或卡死。
类别 D:API 契约和数据处理(API)
| 检查 ID | 检查项 | 标准 | 方法 |
|---|---|---|---|
| API-01 | UI 能妥善处理所有 HTTP 错误代码 | API 契约 | 模拟 400、401、403、404、422、429、500、503 |
| API-02 | UI 遇到 null/undefined 字段时不会崩溃 | 防御性编码 | 模拟包含 null 字段的 API 响应 |
| API-03 | UI 能处理空数组/对象 | 防御性编码 | 模拟包含空集合的 API 响应 |
| API-04 | UI 能处理意外的数据类型 | 防御性编码 | 模拟包含错误类型的 API 响应 |
| API-05 | API 调用期间会显示加载状态 | UX 最佳实践 | 为 API 添加 2 秒延迟,确认加载指示器 |
| API-06 | 能处理竞态条件(过期响应) | 状态管理 | 快速连续触发请求,确认以最新结果为准 |
| API-07 | 对速率限制(429)给予用户反馈 | API 契约 | 模拟 429 响应,检查 UI 反馈 |
| API-08 | 能处理中途会话认证过期 | 会话管理 | 在会话期间模拟 401,检查是否重定向到登录页面 |
**浏览器验证:**使用 page.route() 模拟每种响应场景。确认每种模拟后的 UI 状态。
类别 E:恢复和用户沟通(REC)
| 检查 ID | 检查项 | 标准 | 方法 |
|---|---|---|---|
| REC-01 | 为暂时性故障提供重试机制 | 弹性 | 模拟间歇性故障,检查是否自动重试 |
| REC-02 | 失败后用户可以手动重试 | UX 最佳实践 | 出现错误后,确认有可用的重试操作 |
| REC-03 | 出错时不会丢失进度 | UX 最佳实践 | 填写长表单,触发错误,检查数据是否保留 |
| REC-04 | 会告知用户功能降级情况 | 沟通 | 功能发生故障时,检查是否有降级通知 |
| REC-05 | 恢复操作清晰易用 | NN/g 启发式原则 | 每种错误出现后,评估恢复体验 |
| REC-06 | 后台操作有状态指示器 | UX 最佳实践 | 启动异步操作,确认有进度反馈 |
**浏览器验证:**注入故障,然后验证恢复路径。
阶段 4:报告
生成结构化报告,并保存到 shiplight/reports/resilience-review-{date}.md:
# Resilience Review Report
**Date:** {date}
**URL:** {url}
**Critical flows tested:** {list}
**API dependencies tested:** {count}
**Failure scenarios simulated:** {count}
## Overall Score: {X}/10 | Confidence: {X}%
## Score Breakdown
| Category | Score | Findings |
|----------|-------|----------|
| Error Handling (ERR) | 5/10 | 2 critical, 1 high |
| Graceful Degradation (DEG) | 6/10 | 1 high, 2 medium |
| Empty & Edge States (EDGE) | 4/10 | 1 critical, 3 high |
| API Contract (API) | 7/10 | 1 high, 1 medium |
| Recovery (REC) | 3/10 | 2 high, 1 medium |
## Failure Matrix
| Failure Scenario | Expected Behavior | Actual Behavior | Status |
|-----------------|-------------------|-----------------|--------|
| API returns 500 | Error message + retry | Blank screen | FAIL |
| Network timeout | Loading → timeout message | Infinite spinner | FAIL |
| Empty data set | "No results" message | Blank page | FAIL |
| ... | | | |
## Findings
(structured findings with evidence, screenshots of failure states)
置信度评分
- 90-100%:已注入故障,并在浏览器中验证故障行为
- 70-89%:代码分析显示缺少错误处理,但未在运行时验证
- 50-69%:基于模式的评估(例如,未检测到错误边界)
- 低于 50%:不要报告
第 5 阶段:修复
1. 修复指南(示例)
#### ERR-01: API error shows blank screen instead of error message
**Impact:** Users see empty page, think app is broken, leave
**File:** src/pages/Dashboard.tsx:45
**Current:** `const data = await fetch('/api/data').then(r => r.json())`
**Problem:** No error handling — fetch throws on network error, .json() throws on non-JSON response
**Fix:**
- Wrap in try/catch
- Add error state: `const [error, setError] = useState(null)`
- Render error UI with retry button
- Add React Error Boundary as fallback
2. YAML 回归测试
- name: err-01-api-error-shows-message
description: Verify API failure shows user-friendly error message instead of blank screen
severity: critical
standard: UX-Error-Handling
steps:
- description: Mock the data API to return a 500 error
js: |
await page.route('**/api/data**', route => {
route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({ error: 'Internal Server Error' })
});
});
- URL: /dashboard
- WAIT_UNTIL: Page has finished attempting to load data
timeout_seconds: 15
- VERIFY: An error message is visible explaining that data could not be loaded
- VERIFY: A retry button or recovery action is available to the user
- VERIFY: The page is NOT blank — navigation and header are still visible
将所有 YAML 测试保存到 shiplight/tests/resilience-review.test.yaml。
提示
- 在
description: + js:语句中使用page.route()——它是注入故障的主要工具 - 优先测试最关键的用户流程(结账、注册、核心功能)
- 空白屏幕始终是严重问题——这是最糟糕的故障模式
- 检查
get_browser_console_logs,查看是否存在未捕获的 Promise 拒绝——这表明缺少错误处理 - 边缘情况测试(EDGE 类别)往往能以最少的时间发现最多的问题
- 使用
close_session结束会话,并使用generate_html_report生成证据