bugfix
Original:🇺🇸 English
Translated
Fix a known bug in the Rock RMS codebase. Guides Claude through root cause analysis, minimal correct fix, and a release-note commit message. Use when the user says "fix this bug", "bugfix", "this is broken", "debug this", describes a bug with file paths or issue numbers, or pastes an error/stack trace with intent to fix. Also use when a bug is found by another skill (e.g. /review-conversion, /check) and the user wants it fixed. Do NOT use for: finding bugs (use /check or /review-conversion), adding features, or refactoring.
5installs
Sourcesparkdevnetwork/rock
Added on
NPX Install
npx skill4agent add sparkdevnetwork/rock bugfixTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Rock RMS Bugfix Workflow
You are fixing a known bug in the Rock RMS codebase. Your job is to understand the root cause, apply the minimal correct fix, and produce a commit message that meets Rock's release-note conventions.
The bug report: $ARGUMENTS
Scale to the Bug
Not every bug needs the full investigation process. Match effort to complexity:
- Obvious fix (user gives exact file, line, and what's wrong — e.g., "line 42 uses but should be
>"): Skip straight to Phase 2. Fix it, verify, output the commit message. Don't load reference files or write a root cause summary for something self-evident.>= - Located but unclear (user knows the area but not the exact cause — e.g., "the save button on GroupDetail doesn't persist the description"): Run Phase 1 but keep it proportional. You may not need every sub-step.
- Vague or complex (user describes a symptom with no location — e.g., "after merging two people, their giving history disappears"): Run the full workflow. Load the reference file. These are the bugs that benefit most from systematic investigation.
Use your judgment. The phases below are a toolkit, not a mandatory checklist.
Reference Routing Table
| Reference File | Load When |
|---|---|
| When the root cause isn't immediately obvious — especially for stale data, NullRef, cache, or cross-layer bugs |
Do NOT read reference files for obvious fixes. Load only when investigation is needed.
Phase 1 — Triage
The goal is to understand the bug well enough to fix it correctly on the first attempt. Resist the urge to jump straight to a patch — most regressions come from fixing symptoms instead of causes.
1.1 — Parse the Report
Extract from :
$ARGUMENTS- Symptom: What's broken? (wrong output, crash, UI glitch, data issue)
- Location: File paths, block names, entity names, or areas mentioned
- Issue number: GitHub issue if provided (for the commit message)
#XXXX - Reproduction context: Any steps, conditions, or data states that trigger the bug
1.2 — Locate the Code
Start by finding the relevant files. The bug report may give you exact paths, or you may need to search:
- Block name given → search for the C# class and
Rock.Blocks/for theRock.JavaScript.Obsidian.Blocks/src/component. Check both — the bug could be server-side, client-side, or a mismatch between them..obs - Entity/model name given → search for the entity, then find which blocks or services consume it.
Rock/Model/ - Error message or stack trace given → grep for the exact error string or the deepest Rock method in the stack trace. That's your starting point, not the top of the stack.
- Vague description only → search for keywords from the symptom across the codebase. Cast a wide net first (grep for the feature name), then narrow down by reading the most relevant hits.
1.3 — Investigate the Root Cause
This is the most important step. Don't jump to conclusions — walk the code systematically.
Before starting, read . It catalogs Rock-specific bug patterns organized by symptom (stale data, NullRef, security bypass, UI not updating, wrong query results, thread-safety, data loss, cross-layer mismatches). Match the reported symptom to these patterns — they'll shortcut your investigation significantly.
references/rock-bug-patterns.mdStep A: Find the entry point. Identify the method, event handler, block action, or API endpoint where the buggy behavior starts. For Obsidian blocks, this is often a method on the C# side or a watcher/event handler on the Vue side. For WebForms, look at event handlers like or page lifecycle methods.
BlockActionbtnSave_ClickStep B: Walk the execution path. Follow the logic from the entry point through every service call, query, and conditional branch. Read each method you encounter — don't assume what it does based on its name. Pay special attention to:
- Conditional branches that might take an unexpected path given the bug's trigger conditions
- Values that could be null, empty, zero, or an unexpected type
- Queries that might return no results, multiple results, or stale data
- Properties being set but never persisted (missing )
SaveChanges - Order-of-operations issues where something is read before it's written
Step C: Check recent history. If the bug feels like a regression (it "used to work"), run on the affected file(s) to see recent changes. Read the diffs of suspicious commits — often the bug is a side effect of a recent change that looked correct in isolation.
git log --oneline -20Step D: Search for related code. Before concluding you've found the bug, grep for other callers of the affected method or other places that set the same property. The bug might be in a caller, not the method itself. Also check if there's a cache layer (Rock caches aggressively) that could be serving stale data.
Step E: Confirm root cause vs. symptom. Ask yourself: "If I fix this specific line, will the bug be fully resolved, or will it just move the failure to a different place?" A symptom fix looks like adding a null check to suppress an exception. A root cause fix looks like ensuring the value is populated correctly upstream so the null never occurs. Prefer the latter.
Step F: Trace across layers (if the bug spans C# ↔ TypeScript ↔ SQL). Many Rock bugs look correct in each layer individually but break at the boundary. If the bug involves an Obsidian block:
- Read the C# block class — check what the methods return and what the bags contain.
BlockAction - Read the Vue component — check what it sends in
.obsand what it does with the response.invokeBlockAction - Verify property names match exactly (C# PascalCase → auto-generated camelCase in TypeScript).
- Verify types survive the JSON round-trip (C# → JSON
int?vsnull;0precision;decimalstring format).DateTime - If a query is involved, check that the LINQ translates to the SQL you expect — sometimes EF generates surprising joins or filters.
1.4 — Identify the Domain
Determine the Rock RMS domain for the commit message based on where the bug lives. Use the file path as the primary signal:
| Path contains | Domain |
|---|---|
| AI |
| API |
| CMS |
| Check-in |
| Communication |
| Connection |
| Core |
| CRM |
| Engagement |
| Event |
| Farm |
| Finance |
| Group |
| Lava |
| LMS |
| Mobile |
| Prayer |
| Reporting |
| Workflow |
| Unclear or cross-cutting | Other |
Valid domains (exactly one): , , , , , , , , , , , , , , , , , , ,
AIAPICMSCheck-inCommunicationConnectionCoreCRMEngagementEventFarmFinanceGroupLavaLMSMobilePrayerReportingWorkflowOther1.5 — Summarize Before Fixing
Before writing any code, state:
- Root cause — one sentence explaining why the bug happens
- Fix approach — what you'll change and why that addresses the root cause (not just the symptom)
- Blast radius — what else could be affected by this change (callers, cache, UI, API consumers)
If the root cause is ambiguous or you find multiple possible causes, say so and explain your reasoning before proceeding.
Phase 2 — Fix
2.1 — Apply the Minimal Correct Fix
Change only what's necessary to resolve the root cause. Follow Rock conventions:
- Always use braces, even for single-line /
if/for.else - Use early returns to keep code flat.
- Use instead of
RockDateTime.DateTime - Don't add optional parameters to public methods — add an overload if needed.
- Wrap any usage in
System.Web.#if WEBFORMS - If the fix involves a query change, verify the LINQ pattern follows Rock conventions (avoid in
Guidwhen.Where()is available, use service-layer predicates over inline duplication).Id
2.2 — Add an Engineering Note (If Non-Obvious)
If the fix would confuse a future reader — because the root cause is subtle, the fix looks wrong at first glance, or there's a non-obvious constraint — add an engineering note:
csharp
/*
[Date] - [Author]
[Why this fix exists and what it prevents.]
Reason: [One-line summary.]
*/Skip the note if the fix is self-explanatory (e.g., changing to ).
>>=2.3 — Verify
Run through this checklist after applying the fix:
- Re-read every modified file — not just the changed lines, but the surrounding method to confirm the fix fits the context.
- Public API preserved — did you change a method signature, remove a parameter, or alter return type? If so, check for callers (grep for the method name). Adding an overload is safer than modifying the existing signature.
- Non-buggy case unaffected — does the fix change behavior for inputs that were already working correctly? Walk through the happy path mentally.
- Null safety — if you added a null check, does it handle the null case correctly (early return, default value, exception)? If you removed one, are you sure the value can never be null?
- Cache coherence — if the bug involved cached data, does the fix invalidate the right cache at the right time? Is there a second cache layer you missed?
- Both layers — if the bug spans C# and TypeScript, did you fix both sides? A C# fix alone may leave the Vue component in an inconsistent state.
- Run to confirm the fix compiles. Suggest the user run
/buildif relevant tests exist./test
2.4 — Escalate If Needed
Some bugs can't be fixed with a code change alone. Stop and tell the user if the fix requires:
- A database migration — schema change, new column, index, or data backfill. Suggest using or
/migration./plugin-migration - A SQL data fix — corrupted data in production that needs a script. Suggest using .
/sql - A breaking API change — the fix would change a public method signature that plugins depend on. Discuss the deprecation approach with the user.
- A Rock framework change — the bug is in core infrastructure, not in a block or service. These changes have a much larger blast radius and need extra review.
Rock.dll - A cache architecture change — the fix requires changing how or when a cache is populated/invalidated at a systemic level, not just adding a call.
FlushItem()
Phase 3 — Commit Message
Output a ready-to-use commit message following Rock's release-note convention.
Format
+ (Domain) Fixed [concise description of what was broken]. (Fixes #XXXX)Rules:
- Start with (past tense) — this classifies it as a Bug Fix in release notes.
Fixed - The description should be readable as a standalone release note — someone scanning the changelog should understand what was wrong without seeing the code.
- Include only if an issue number was provided in the bug report.
(Fixes #XXXX) - Use exactly one domain from the list above.
- If the fix is trivial (typo, unused import, whitespace) and doesn't warrant a release note, use the prefix instead:
-- Fixed typo in variable name.
Examples
+ (Core) Fixed the friendly schedule text display for single-date schedules. (Fixes #6694)
+ (Finance) Fixed ACH transactions failing when the gateway returns a null reference number.
+ (CRM) Fixed duplicate detection not considering middle name during merge.
+ (Group) Fixed group member role dropdown not respecting the configured sort order.
- Fixed incorrect variable name in ConnectionRequestService.Output
Present the commit message in a code block so the user can copy it directly. If you're uncertain about the domain or description, offer alternatives and let the user choose.
Examples
Example 1 — Obvious fix (skip straight to Phase 2):
User says: "The save button on GroupDetail doesn't persist the description field. The description textarea is reading from instead of ."
bag.namebag.descriptionThe user identified the exact cause. Go directly to Phase 2 — fix the property reference, re-read the surrounding method, run , and output the commit message. No need to load reference files or write a root cause summary.
/buildExample 2 — Vague/complex bug (full workflow):
User says: "After merging two people, their giving history disappears."
This needs the full workflow. Load — the "PersonAlias vs Person confusion" pattern is likely relevant. Trace the merge logic to find where is used instead of , confirm by checking the FK relationships, then apply the minimal fix in Phase 2.
references/rock-bug-patterns.mdPersonIdPersonAliasIdTroubleshooting
These are common problems you may hit during the bugfix workflow itself:
Fix doesn't compile. Run , read the exact error. Common causes: missing statement for a type you referenced, wrong parameter type in a method call, or a property name that doesn't exist on the bag. Fix the compilation error — don't skip the build check.
/buildusingRoot cause unclear after investigation. Widen the search: check on affected files for recent regressions, grep for other callers of the suspect method, and look one layer up (the bug may be in a caller, not the method itself). If still unclear, ask the user for reproduction steps or specific data conditions that trigger it.
git log --oneline -20Multiple possible root causes. State all candidates with your reasoning for each. Recommend fixing the most likely one first, and explicitly note the others so the user can investigate further if the first fix doesn't resolve it. Don't silently pick one and ignore the rest.