agentleFS
HainrixzHainrixz/claude-db/skills/db-migration-safety/SKILL.md

db-migration-safety

Skill22 starsChanged 5 months agoMITView on GitHub

Migration-safety lint (M22) — the static contract the migration-safety auditor (MSA) and db-migration-writer enforce on a candidate migration BEFORE it runs. Checks reversibility (down migration present / expand-contract), lock level (does it take ACCESS EXCLUSIVE on a hot table), table rewrite (full-table rewrites on type/default changes), destructive ops (DROP COLUMN/TABLE, TRUNCATE), unsafe enum mutation, NOT NULL without default on a large table, and schema drift between the declarative artifact and migration history. Feeds the Performance & Scale score.

  • Deletes or force-pushes

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Only DROP/TRUNCATE-class destructive and irreversible migrations cap performance at sev 5.

    line 72
  2. Distinctive:

    Read-only: M22 lints and proposes.

    line 74

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md
<!-- Copyright (c) 2026 Enrique Rocha (@soyenriquerocha) · tododeia.com · id er-f37b7121 -->

db-migration-safety (M22) — the migration lint contract

M22 lints a candidate migration as a static artifact before execution. It is the contract the migration-safety auditor and the db-migration-writer agent both honor. Feeds Performance & Scale (Almacenamiento/operability category). A destructive irreversible migration is the sev-5 cap on the performance axis.

What it checks (the lint contract)

  1. Reversibility — a usable down/rollback exists, or the change follows expand-contract (add-new → backfill → switch → drop-old in separate deploys). A one-shot destructive step with no down is the highest-severity finding here.
  2. Lock level — does the statement take a blocking lock on a hot table? In Postgres: adding a column with a volatile default (pre-11), ALTER COLUMN TYPE, adding a CHECK/FK without NOT VALID, non-CONCURRENTLY index creation all take ACCESS EXCLUSIVE / block writes. Prefer CREATE INDEX CONCURRENTLY, ADD CONSTRAINT ... NOT VALID then VALIDATE CONSTRAINT.
  3. Table rewrite — changes that force a full-table rewrite (certain ALTER COLUMN TYPE, adding a NOT NULL column with a volatile default on old engines) → slow + long lock on large tables.
  4. Destructive ops — DROP COLUMN, DROP TABLE, TRUNCATE, DROP NOT NULL reversals, dropping a column still read by deployed code. Destructive + irreversible = sev 5 (caps performance).
  5. NOT NULL without default added to a populated table → fails or locks; require a backfill plan.
  6. Enum mutation — the durable concern: enum values cannot be removed or reordered (removal is unsupported; renaming/reordering breaks dependents), so a changing set should be a lookup table, not a native enum. ALTER TYPE ... ADD VALUE is append-only and runs in a transaction on PG12+ (only older PG forbade it mid-txn). Flag enum changes; suggest lookup tables.
  7. Schema drift — the declarative artifact (schema.prisma / structure.sql / snapshot) disagrees with the migration history (a column exists in one but not the other) → directional warn.

Tier-0 static checks

Parse migration SQL / ORM migration files (scripts/parse-schema.mjs, parse-orm-python.py). Scan for: DROP TABLE|DROP COLUMN|TRUNCATE; ALTER COLUMN .* TYPE; ADD COLUMN .* NOT NULL without DEFAULT; CREATE INDEX lacking CONCURRENTLY; ADD CONSTRAINT (FK/CHECK) lacking NOT VALID; ALTER TYPE .* ADD VALUE / enum value removal or reorder; absence of a down/rollback block; drift between the authoritative artifact (references/detection-signals.md precedence) and the latest migration.

Tier-1 verification query

  • Affected-table size (does the lock matter?): SELECT pg_size_pretty(pg_total_relation_size('<t>')), reltuples FROM pg_class WHERE relname='<t>';
  • Lock the statement would take: EXPLAIN/pg_locks inspection, or a dry_run_migration against a throwaway copy / shadow DB. Use verification.method: dry_run_migration when a shadow DB is available; otherwise migration_lint on the static SQL. When live size is needed to decide severity but no DB is reachable → needs_api, never a silent pass.

Findings

Emit per schema/finding.schema.json. Example ids:

  • M22.20240115_drop_users_legacy.destructive_irreversible — DROP COLUMN with no down and column still referenced (fail, severity 5, axis performance, fixable proposed → expand-contract plan).
  • M22.add_index.lock_blocking — CREATE INDEX without CONCURRENTLY on a hot table (warn, severity 4, axis performance, fixable auto → add CONCURRENTLY).
  • M22.add_email_notnull.notnull_no_default — ADD COLUMN ... NOT NULL no default on a populated table (fail, severity 4, axis performance, fixable proposed).
  • M22.status_enum.enum_value_removed — enum value removed/reordered (unsupported; breaks dependents) — suggest a lookup table (warn, severity 3, axis performance).
  • M22.drift.column_in_artifact_not_migration — schema drift (warn, severity 2, axis performance, confidence directional). Each finding: evidence.observed quotes the offending migration statement verbatim (secrets redacted); verification.reproduce is a runnable command above using $DATABASE_URL; verification.method is migration_lint or dry_run_migration; fix_preview carries the safer rewrite (e.g. CONCURRENTLY, NOT VALID + VALIDATE, an expand-contract sequence); expected_impact carries {axis, confidence, magnitude, rationale} — banded, never a naked %.

Honesty

  • Severity of a lock depends on table size and write rate — without live evidence, a blocking op on an unknown-size table is directional (medium), not an established sev-5. Don't claim a downtime duration in seconds; magnitude banded only.
  • Only DROP/TRUNCATE-class destructive and irreversible migrations cap performance at sev 5. Reversible or expand-contract changes are warns. Drift is directional and never caps.
  • Read-only: M22 lints and proposes; it never executes a migration. Execution is the writer agent's job behind explicit user accept.

Download now (ZIP)

Does 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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.