impact-assessment
Skill2 starsChanged 36 days agoMITView on GitHub
Assess the impact of a production bug (scope, duration, affected data) and generate a rake task to remediate any data issues
In this repository75 other files it gives its agents.
- acceptance-criteriaSkill
- architect-guideSkill
- architect-reviewSkill
- audit-fixerSkill
- avo-admin-expertSkill
- backend-services-expertSkill
- bug-hunt-allSkill
- bug-hunt-fixSkill
- bug-huntSkill
- build-feature-remoteSkill
- build-featureSkill
- codeSkill
- component-testSkill
- controller-expertSkill
- create-qa-documentSkill
- debugSkill
- devops-expertSkill
- execute-qaSkill
- feature-qaSkill
- fix-bug-indexSkill
- fix-honeybadgerSkill
- fix-spec-bugsSkill
- fix-system-testSkill
- frontend-expertSkill
- frontend-reviewSkill
- full-qa-fixSkill
- full-qaSkill
- full-reviewSkill
- green-ciSkill
- group-issuesSkill
- honeybadger-auditSkill
- ideateSkill
- improveSkill
- merge-mainSkill
- model-expertSkill
- model-testSkill
- native-bug-hunt-fixSkill
- native-bug-huntSkill
- page-speedSkill
- plan-questionsSkill
- planSkill
- plan-system-testsSkill
- policy-testSkill
- prdSkill
- prd-worktreeSkill
- product-questionSkill
- product-question-tldrSkill
- qa-branchSkill
- qa-testerSkill
- refactor-sweepSkill
- resolve-honeybadgerSkill
- resolve-issueSkill
- resolve-issuesSkill
- review-acceptance-criteriaSkill
- review-fixesSkill
- review-railsSkill
- rspec-test-expertSkill
- scale-reviewSkill
- service-testSkill
- settle-pr-reviewSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
12 rules. About 0 are common, 8 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
Before running this skill, you should already know:
- Very specific: line 18
If the root cause is not yet known, run /fix-honeybadger or /debug first.
- Very specific: line 34
If $ARGUMENTS includes a Honeybadger fault ID, use it directly.
- Distinctive: line 66
Bug introduced: Check git history for when the causal change was deployed
- Distinctive: line 72
Fix deployed: When the fix PR was merged/deployed (or "pending" if not yet deployed)
- Very specific: line 97
Create a rake task to discover affected records.
- Distinctive: line 166
Input-driven: Only fixes records identified by the diagnostic script — no independent querying
- Distinctive: line 302
Ask the user to confirm:
- Very specific: line 313
If this skill is being run alongside /fix-honeybadger (worktree exists):
- Distinctive: line 332
If this is a standalone run (no worktree), stage and commit normally.
- Distinctive: line 336
If a PR already exists, update its description to include the impact assessment and run instructions:
- Distinctive: line 438
If the bug only caused errors (e.g., 500 pages, failed loads) without corrupting data:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Impact Assessment & Data Remediation
Assess the real-world impact of a production bug and create scripts to diagnose and fix any data damage. This skill is designed to run after the root cause is known — typically after /fix-honeybadger or /debug has identified the problem.
Prerequisites
Before running this skill, you should already know:
- The Honeybadger fault ID (or error details)
- The root cause of the bug
- What the fix looks like (or it's already implemented)
If the root cause is not yet known, run /fix-honeybadger or /debug first.
Key Constraint
Claude has read-only access to the production database through bin/prod-read / bin/prod-sql (a read-only database user; see CLAUDE.md "Production Safety" and docs/PROD_READ_ACCESS.md) and no write access. This skill produces two scripts:
- Diagnostic script — read-only; Claude runs it against production itself with
bin/prod-read, outputs JSON with affected record IDs and details - Remediation rake task — accepts the diagnostic output as input, fixes the affected records; the user runs it in production after a database snapshot
This ensures all data in the impact assessment is real production data, never estimates.
You never write to production yourself. You author the remediation rake task and hand the user the run commands (dry run → flyadmin mpg backup create <cluster-id> → apply); they run them in their own terminal (flyadmin = fly with an admin-scoped token; your read-only token cannot write).
Phase 1: Gather Impact Data from Honeybadger
Step 1: Identify the Fault
If $ARGUMENTS includes a Honeybadger fault ID, use it directly. Otherwise, find the relevant fault:
mcp__honeybadger__list_projects
mcp__honeybadger__list_faults(project_id: <id>, q: "<error class or description>")Step 2: Collect Scope Data
Gather comprehensive impact metrics using the Honeybadger MCP tools:
# Fault details (occurrences, first/last seen)
mcp__honeybadger__get_fault(project_id: <id>, fault_id: <fault_id>)
# All affected users with occurrence counts
mcp__honeybadger__list_fault_affected_users(project_id: <id>, fault_id: <fault_id>)
# Recent notices for request context and patterns
mcp__honeybadger__list_fault_notices(project_id: <id>, fault_id: <fault_id>)
# Occurrence trends over time
mcp__honeybadger__get_project_occurrence_counts(project_id: <id>, period: "day")
# Notices by user breakdown
mcp__honeybadger__get_project_report(project_id: <id>, report: "notices_by_user", start: "<first_seen>", stop: "<now>")Step 3: Compile Duration Timeline
Build a timeline from the data:
- Bug introduced: Check git history for when the causal change was deployed
git log --oneline --after="<date_before_first_seen>" --before="<first_seen_date>" -- <affected_files> - First occurrence: From Honeybadger fault
created_at - Last occurrence: From Honeybadger fault
last_notice_at - Fix deployed: When the fix PR was merged/deployed (or "pending" if not yet deployed)
Calculate the exposure window (time between bug introduction and fix deployment).
Phase 2: Assess Data Impact
Step 4: Determine Data Damage
Based on the root cause, answer these questions:
- Was data corrupted? — Did the bug cause incorrect values to be written to the database?
- Was data lost? — Did the bug prevent data from being saved that should have been?
- Was data duplicated? — Did the bug cause duplicate records?
- Were side effects skipped? — Did the bug prevent callbacks, emails, notifications, or jobs from firing?
- Were external systems affected? — Did bad data flow to Stripe, Stedi, Google Calendar, or other integrations?
For each "yes", identify:
- Which models/tables are affected
- How to query for affected records
- How to determine the correct state
Phase 3: Create the Diagnostic Script
Step 5: Design the Diagnostic Script
Create a rake task to discover affected records. It runs locally against production through bin/prod-read (the diagnostic is plain Ruby, so pipe the task body — or a tmp/diagnose_<short_description>.rb copy of it — into bin/prod-read; the read-only user makes any write raise PG::InsufficientPrivilege). This script:
- Only reads data — never writes or modifies anything
- Outputs JSON to stdout — structured data that can be piped to the remediation task
- Scoped to the exposure window — only queries records within the affected time range
- Tenant-aware — uses
ActsAsTenant.without_tenantto query across all organizations - PHI-safe — outputs record IDs and minimal metadata, no client names/DOBs/etc.
Step 6: Implement the Diagnostic Script
File: lib/tasks/diagnose_<short_description>.rake
# lib/tasks/diagnose_<short_description>.rake
namespace :data do
desc "Diagnose data affected by Honeybadger fault #<fault_id>: <short description>"
task diagnose_<short_description>: :environment do
results = {
fault_id: <fault_id>,
description: "<what this diagnoses>",
exposure_window: {
start: "<first_seen>",
stop: "<last_seen>"
},
diagnosed_at: Time.current.iso8601,
affected_records: []
}
ActsAsTenant.without_tenant do
scope = ModelName.where(created_at: "<first_seen>".."<last_seen>")
.where(<condition_matching_potentially_affected>)
$stderr.puts "Scanning #{scope.count} potentially affected records..."
scope.find_each do |record|
# Determine if this record is actually affected
next unless <condition_confirming_damage>(record)
results[:affected_records] << {
id: record.id,
model: record.class.name,
organization_id: record.organization_id,
# Include fields needed by the remediation task to apply the fix
current_value: record.<damaged_field>,
expected_value: <how_to_determine_correct_value>(record)
# Add any other fields the remediation task needs
}
end
end
results[:total_affected] = results[:affected_records].size
$stderr.puts "Found #{results[:total_affected]} affected records."
# Output JSON to stdout so it can be captured and passed to remediation
puts results.to_json
end
endKey design decisions:
- Progress/status messages go to
$stderrso they don't pollute the JSON on$stdout - The JSON includes everything the remediation task needs — record IDs, current values, expected values
- Each record entry includes
organization_idso the remediation task can set tenant context
Phase 4: Create the Remediation Rake Task
Step 7: Design the Remediation Rake Task
The rake task accepts the diagnostic JSON as input and fixes the identified records. It must be:
- Input-driven: Only fixes records identified by the diagnostic script — no independent querying
- Idempotent: Safe to run multiple times without causing additional damage
- Dry-run by default: Print what would change unless
DRY_RUN=falseis passed - Logged: Print clear output for every record processed
- Tenant-aware: Set
ActsAsTenant.current_tenantper record using theorganization_idfrom the diagnostic output
Step 8: Implement the Remediation Rake Task
File: lib/tasks/remediate_<short_description>.rake
# lib/tasks/remediate_<short_description>.rake
namespace :data do
desc "Remediate data affected by Honeybadger fault #<fault_id>: <short description>"
task remediate_<short_description>: :environment do
dry_run = ENV.fetch("DRY_RUN", "true") != "false"
input_file = ENV.fetch("INPUT") { abort "ERROR: Pass INPUT=path/to/diagnosis.json or pipe from stdin" }
diagnosis = JSON.parse(
input_file == "-" ? $stdin.read : File.read(input_file)
)
affected_records = diagnosis["affected_records"]
puts "=" * 60
puts "Remediation: <description of what this fixes>"
puts "Honeybadger Fault: ##{diagnosis['fault_id']}"
puts "Diagnosis from: #{diagnosis['diagnosed_at']}"
puts "Records to process: #{affected_records.size}"
puts "Mode: #{dry_run ? 'DRY RUN (pass DRY_RUN=false to apply)' : 'LIVE — changes will be applied'}"
puts "=" * 60
puts
fixed_count = 0
skipped_count = 0
error_count = 0
affected_records.each do |entry|
record_id = entry["id"]
model_class = entry["model"].constantize
org = Organization.find(entry["organization_id"])
ActsAsTenant.with_tenant(org) do
record = model_class.find_by(id: record_id)
unless record
puts " [SKIP] #{entry['model']} ##{record_id}: record not found (already deleted?)"
skipped_count += 1
next
end
# Check if the record still needs fixing (idempotency)
unless <condition_still_needs_fix>(record, entry)
puts " [SKIP] #{entry['model']} ##{record_id}: already correct"
skipped_count += 1
next
end
if dry_run
puts " [DRY RUN] Would fix #{entry['model']} ##{record_id}: " \
"#{entry['current_value']} -> #{entry['expected_value']}"
else
begin
record.update!(<corrected_attributes_from_entry>(entry))
fixed_count += 1
puts " [FIXED] #{entry['model']} ##{record_id}: " \
"#{entry['current_value']} -> #{entry['expected_value']}"
rescue => e
error_count += 1
puts " [ERROR] #{entry['model']} ##{record_id}: #{e.message}"
end
end
end
end
puts
puts "=" * 60
puts "Records in diagnosis: #{affected_records.size}"
puts "To apply: bundle exec rake data:remediate_<short_description> INPUT=diagnosis.json DRY_RUN=false" if dry_run
puts "=" * 60
# RESULT is always the last line: the go / no-go blurb in the run instructions quotes it.
if dry_run
puts "RESULT: would_fix=#{affected_records.size - skipped_count} skipped=#{skipped_count} errors=#{error_count} (dry run)"
else
puts "RESULT: fixed=#{fixed_count} skipped=#{skipped_count} errors=#{error_count}"
end
end
endStep 9: Verify the Rake Tasks
- Verify both tasks compile — ensure they load without syntax errors:
bundle exec rake -T data:diagnose_<short_description> data:remediate_<short_description> - Review the logic — walk through query scope, conditions, JSON structure, and fix logic
Phase 5: Present Impact Report & Get Confirmation
Step 10: Generate Impact Summary
Present the assessment to the user. Note that record counts will be filled in after they run the diagnostic script.
## Impact Assessment: Honeybadger Fault #<fault_id>
### Scope (from Honeybadger)
- **Error**: `<ErrorClass>` — <error message>
- **Total occurrences**: <count>
- **Affected users**: <count>
- **Affected organizations**: <list if determinable from Honeybadger>
- **Affected feature**: <which part of the app>
### Duration
- **Bug introduced**: <date> (commit <sha>)
- **First occurrence**: <date>
- **Last occurrence**: <date>
- **Exposure window**: <X days/hours>
- **Fix status**: <deployed/pending>
### Data Impact (theoretical — run diagnostic to confirm)
- **Nature of damage**: <corrupted/lost/duplicated/skipped side effects>
- **Models affected**: <ModelName>
- **External systems**: <affected/not affected>
- **Details**: <specific description of what went wrong with the data>
### Remediation Required
- [ ] <specific remediation action 1>
- [ ] <specific remediation action 2>
- [ ] <notify affected users? yes/no and why>Step 11: Get User Confirmation
Ask the user to confirm:
- Whether the impact assessment looks accurate
- Whether they want to proceed with committing the scripts
- Whether any additional remediation is needed (e.g., user notification, Stripe adjustments)
Do NOT proceed to Phase 6 without user confirmation.
Phase 6: Commit & Update PR
Step 12: Add Scripts to the PR
If this skill is being run alongside /fix-honeybadger (worktree exists):
cd "$WORKTREE_DIR"
git add lib/tasks/diagnose_<short_description>.rake lib/tasks/remediate_<short_description>.rake
git commit -m "$(cat <<'EOF'
Add diagnostic and remediation scripts for Honeybadger fault #<fault_id>
Diagnostic: Identifies <ModelName> records affected during the exposure
window (<start_date> to <end_date>). Outputs JSON to stdout.
Remediation: Accepts diagnostic JSON as input and fixes affected records.
Dry-run by default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"If this is a standalone run (no worktree), stage and commit normally.
Step 13: Update the PR Description
If a PR already exists, update its description to include the impact assessment and run instructions:
gh pr edit <pr_number> --body "$(cat <<'EOF'
<existing PR body>
## Impact Assessment
### Scope
- **Total occurrences**: <count>
- **Affected users**: <count>
- **Exposure window**: <duration>
### Data Remediation
Two rake tasks are included for data remediation:
**Step 1: Diagnose** — Run in production to identify affected records:
```bash
bundle exec rake data:diagnose_<short_description> > diagnosis.jsonReview the output:
cat diagnosis.json | python3 -m json.toolStep 2: Remediate (dry-run) — See what would be fixed:
bundle exec rake data:remediate_<short_description> INPUT=diagnosis.jsonStep 3: Remediate (apply) — Fix the affected records:
bundle exec rake data:remediate_<short_description> INPUT=diagnosis.json DRY_RUN=falseDry run — go / no-go. Safe to apply when the dry run's last line reads
RESULT: would_fix=<N> skipped=0 errors=0 (dry run) with <N> equal to the record count in
diagnosis.json, and every [DRY RUN] Would fix … line shows the expected current -> expected
change. Stop and report back if errors is non-zero, would_fix differs from <N>, or any
[ERROR] / [SKIP] line appears that the diagnosis did not predict.
Post-Deploy Checklist
- Deploy the code fix
- Run diagnostic script in production:
bundle exec rake data:diagnose_<short_description> > diagnosis.json - Review
diagnosis.json— confirm affected records look correct - Run remediation in dry-run:
bundle exec rake data:remediate_<short_description> INPUT=diagnosis.json - Review dry-run output — last line matches the go / no-go blurb above
- Run remediation for real:
bundle exec rake data:remediate_<short_description> INPUT=diagnosis.json DRY_RUN=false - Verify affected records are corrected
- Monitor Honeybadger for recurrence EOF )"
## Phase 7: Final Report
### Step 14: Present Summary
Impact Assessment Complete
Fault: Honeybadger #<fault_id> — <ErrorClass>
Impact (from Honeybadger)
- Users affected:
<count> - Exposure window:
<duration>(<start>to<end>)
Deliverables
- Diagnostic script:
lib/tasks/diagnose_<short_description>.rake - Remediation script:
lib/tasks/remediate_<short_description>.rake - PR updated with impact assessment and post-deploy checklist
Post-Deploy Instructions (user runs steps 1 and 4–6 in their own terminal)
- Deploy the fix:
bin/deploy production - Run diagnostic (Claude, read-only):
bin/prod-read < tmp/diagnose_<short_description>.rb > tmp/diagnosis.json - Review
tmp/diagnosis.json - Dry-run remediation:
flyadmin ssh console -a <app-name> -C "sh -c 'bin/rails data:remediate_<short_description> INPUT=-'" < tmp/diagnosis.jsonGo when the last line readsRESULT: would_fix=<N> skipped=0 errors=0 (dry run)(N = records indiagnosis.json); stop on non-zeroerrorsor a differentwould_fix. - Snapshot the database:
flyadmin mpg backup create <cluster-id> - Apply remediation:
flyadmin ssh console -a <app-name> -C "sh -c 'DRY_RUN=false bin/rails data:remediate_<short_description> INPUT=-'" < tmp/diagnosis.json - Monitor Honeybadger for 24 hours
## Important Guidelines
1. **Never modify production data directly** — always use a rake task that can be reviewed and audited; the user runs it, and the run instructions always put `flyadmin mpg backup create <cluster-id>` between the dry run and the apply
2. **Two-script pattern** — diagnostic script reads and outputs JSON; remediation script consumes that JSON
3. **Diagnostic script is read-only** — it must never write to the database
4. **Remediation script is input-driven** — it only fixes records listed in the diagnostic output, never queries independently
5. **Dry-run by default** — the remediation task must be safe to run without `DRY_RUN=false`
6. **Idempotency** — both scripts must be safe to run multiple times
7. **Ask before proceeding** — always get user confirmation before committing scripts
8. **Tenant awareness** — use `ActsAsTenant.without_tenant` in diagnostic, `ActsAsTenant.with_tenant` per-record in remediation
9. **PHI sensitivity** — script output should include record IDs but minimize PHI (no client names, DOBs, etc.)
10. **No silent failures** — log every record examined, every change made, and every error encountered
12. **Checkable ending** — the remediation task prints a `DRY RUN` / `LIVE` banner first and ends with exactly one `RESULT: would_fix=… skipped=… errors=…` line (`fixed=` in live mode, `(dry run)` suffix in dry-run mode), and the run instructions carry a go / no-go blurb quoting that line with expected numbers (CLAUDE.md "Writing to production")
11. **stderr for status, stdout for data** — diagnostic script sends progress to `$stderr`, JSON to `$stdout`
## When No Data Remediation Is Needed
If the bug only caused errors (e.g., 500 pages, failed loads) without corrupting data:
1. Complete Phases 1-2 (Honeybadger data + damage assessment)
2. Note "No data remediation required — bug caused user-facing errors only, no data corruption"
3. Skip Phases 3-4 (no scripts needed)
4. Still update the PR with the impact assessment for the recordDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

