Create or review Rock RMS plugin migrations (hotfixes) in Rock/Plugin/HotFixes/. Plugin migrations are single .cs files with sequential numbering and a [MigrationNumber] attribute. Use when the user says "create a plugin migration", "plugin migration", "hotfix migration", "new hotfix", "write a hotfix", "review plugin migration", "check this hotfix", "audit hotfix migration", or needs to create a data fix, configuration change, attribute update, or stored procedure update that ships as a plugin migration. Also use when the user describes a fix or change that targets Rock/Plugin/HotFixes/. Do NOT use for EF migrations in Rock.Migrations/ — use /migration instead. Do NOT use for standalone SQL scripts — use /sql instead.
You are creating or reviewing a plugin migration (hotfix) in the Rock RMS codebase. Plugin migrations are single .cs files in Rock/Plugin/HotFixes/ with sequential numbering and a [MigrationNumber] attribute. They inherit from Rock.Plugin.Migration and provide Up() and Down() methods.
The user's request: $ARGUMENTS
Load reference files progressively — only when needed.
| Reference File | Load When |
|---|---|
references/hotfix-patterns.md | Before writing migration logic (always in write mode) |
references/methods-and-sql.md | When choosing methods, writing SQL, or working with stored procedures |
references/common-pitfalls.md | Before finalizing any migration — both write and review modes |
Do NOT read all files upfront. Read hotfix-patterns.md always for write mode; read others only when their trigger condition is met.
Parse what the migration needs to do and determine which mode to use:
Write mode — The user describes what the migration should accomplish, or says "create", "write", "new". Proceed to Step 2 (Write Mode).
Review mode — The user says "review", "check", "audit", or names an existing migration file. Proceed to Step 2 (Review Mode).
Migration categories (for write mode):
If ambiguous, ask clarifying questions before proceeding.
Scan Rock/Plugin/HotFixes/ for the highest existing migration number:
Glob: Rock/Plugin/HotFixes/*.cs
Parse the leading number from each filename (e.g., 279_MigrationRollupsForV18_3_0_1.cs → 279).
Next number = highest + 1
Determine minimum Rock version:
Generate filename: {number}_{PascalCaseDescription}.cs
Before writing the migration, you must understand the actual database schema. Do not guess column names, types, or relationships.
Read the model files for every entity you're touching:
Rock/Model/[Domain]/[Entity]/[Entity].csRock/Model/**/{EntityName}.cs[Required] (NOT NULL), [MaxLength(N)] (string limits), FK navigation properties, enum-typed propertiesUnderstand Rock's standard column patterns:
Model<T> has: Id (identity), Guid (uniqueidentifier), IsSystem (bit), CreatedDateTime, ModifiedDateTime, CreatedByPersonAliasId, ModifiedByPersonAliasIdCreatedByPersonAliasId, ModifiedByPersonAliasId) reference [PersonAlias], NOT [Person]ON DELETE SET NULL[Order] columns should be calculated from existing max, not hardcodedCheck SystemGuid files: Rock/SystemGuid/{EntityType}.cs for well-known GUIDs
Check enum definitions: Rock.Enums/[Domain]/ for integer values of enum-typed columns
Load references:
references/hotfix-patterns.md for common patterns and complete examplesreferences/methods-and-sql.md if using RockMigrationHelper, stored procedures, or complex SQLUse the following template. The copyright block, namespace, class structure, and XML doc comments must match exactly:
// <copyright>
// Copyright by the Spark Development Network
//
// Licensed under the Rock Community License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.rockrms.com/license
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System;
namespace Rock.Plugin.HotFixes
{
/// <summary>
/// [Description of what this migration does]
/// </summary>
/// <seealso cref="Rock.Plugin.Migration" />
[MigrationNumber( {number}, "{minRockVersion}" )]
public class {ClassName} : Migration
{
/// <summary>
/// Operations to be performed during the upgrade process.
/// </summary>
public override void Up()
{
// Migration logic here
}
/// <summary>
/// Operations to be performed during the downgrade process.
/// </summary>
public override void Down()
{
// Down migrations are not yet supported in plug-in migrations.
}
}
}
For available methods (Sql(), SqlScalar(), RockMigrationHelper.*, EF wrappers), SQL formatting rules, string escaping, stored procedure patterns, and code organization conventions, consult references/methods-and-sql.md.
Read references/common-pitfalls.md and run through the pre-finalization checklist before presenting.
Output: Write the .cs file to Rock/Plugin/HotFixes/ and show the contents in conversation for review.
$ARGUMENTS names a specific file or migration number, find it in Rock/Plugin/HotFixes/Glob: Rock/Plugin/HotFixes/*.cs
Before reviewing, gather the context needed to judge correctness:
Rock/Model/[Domain]/[Entity]/[Entity].cs) for every entity the migration touches — verify column types, [Required], [MaxLength], nullable, FK navigation propertiesRock/SystemGuid/ files if the migration references GUIDsRock.Enums/[Domain]/ if the migration uses enum integer valuesreferences/hotfix-patterns.md for expected patternsreferences/common-pitfalls.md for known failure modesRun through the pre-finalization checklist from references/common-pitfalls.md, plus these additional review-specific checks:
Rock.Plugin.Migration[MigrationNumber] attribute present with valid number and versionPresent findings using severity levels:
| Severity | Meaning | Examples |
|---|---|---|
| CRITICAL | Must fix — will cause errors or data loss | Wrong block type method, missing string escaping, SQL syntax error |
| WARNING | Should fix — could cause issues or violates conventions | Missing IF NOT EXISTS guard, magic string GUIDs, wrong GUID casing |
| NOTE | Consider — minor improvement or style suggestion | Missing XML doc comment, could use private const string for repeated GUIDs |
Format each finding as:
[SEVERITY-N] Short title
Description of the issue and what to change.
Line/area: [where in the file]
End with a summary: total findings by severity and a go/no-go recommendation.
If the migration is clean: Say so. Don't invent issues to fill a report.
User says: "Fix the SQL runner warning block HTML to use proper Bootstrap classes"
Actions:
Result: File written to Rock/Plugin/HotFixes/280_FixSqlRunnerWarningHtml.cs with a Sql() UPDATE on [HtmlContent] targeting the known Guid.
User says: "Add a 'ShowHeader' boolean attribute to the PersonBio block type"
Actions:
Result: File written with RockMigrationHelper.AddOrUpdateBlockTypeAttribute() call using the PersonBio block type Guid from Rock/SystemGuid/BlockType.cs.
User says: "Add a run-once job to fix broken achievement types from the v18.0 bug"
Actions:
using Rock.Model; for typeof() referenceResult: File written with AddPostUpdateServiceJob() using typeof(Rock.Jobs.PostUpdateJobs.PostV183UpdateAchievementTypes).FullName and the correct SystemGuid.
User says: "Update the SynchronizeListRecipients proc to exclude archived members"
Actions:
references/methods-and-sql.md for stored procedure patternResult: File written with the full stored procedure pattern including session setting save/restore and IF EXISTS guard.
User says: "review my plugin migration" or /plugin-migration review
Actions:
Rock/Plugin/HotFixes/Result: Severity-based findings report with actionable fix suggestions and a go/no-go recommendation.
Migration number conflict: Another developer may have used that number. Re-scan the directory for the latest number after pulling latest.
"Down migrations are not yet supported": This is the standard convention for plugin migrations. Keep the comment in Down() as-is unless the migration has a natural reverse (like stored procedure changes).
Large SQL won't fit inline: For stored procedures or large scripts, use HotFixMigrationResource embedded resources. Add the SQL to the .resx file and reference it as HotFixMigrationResource._NNN_Description_ProcedureName.
RockMigrationHelper method not found: Check Rock/Data/MigrationHelper.cs for the exact method signature and overloads.
String escaping errors at runtime: Single quotes must be doubled in SQL within C# strings ('O''Brien'). Curly braces must be doubled in $@"..." strings ({{, }}). See references/common-pitfalls.md for full examples.
Wrong block type method (data loss risk): Never use UpdateBlockTypeByGuid() for Obsidian or Mobile blocks — it can delete entity-based block types. Use AddOrUpdateEntityBlockType() instead. See references/common-pitfalls.md for details.
Missing using Rock.Model;: Required when using typeof() for job types or entity types. Without it, the type reference may not resolve correctly.