Agent skill

refactor-break-bw-compat

Refactor by removing backward compatibility and legacy layers. Use when modernizing APIs, cleaning up migration debt, removing compat shims, or eliminating stale feature flags.

Stars 17
Forks 0

Install this agent skill to your Project

npx add-skill https://github.com/OutlineDriven/odin-claude-plugin/tree/main/skills/refactor-break-bw-compat

SKILL.md

Breaking Refactors — Freedom Through Structure

Compatibility layers are coupling debt with interest. Every compat shim is a decision deferred, not a decision avoided. Break cleanly, break once, break with evidence.

Principles

  1. No half-measures. A partial migration is worse than no migration — it doubles the surface area and confuses every reader.
  2. One migration direction. Old-to-new only. Never add new-to-old adapters; that entrenches the old path.
  3. Blast radius awareness. Map every consumer before removing anything. Surprise breakage is a planning failure, not a courage signal.
  4. Dead code is a lie. "Just in case" code is not dead — it actively misleads readers about what the system does.
  5. Compat shims are temporary. If a shim has no removal date, it is permanent. If it is permanent, it is architecture. Decide which.

Reconnaissance Checklist

Before breaking anything, find and catalog:

  • @deprecated / #[deprecated] / warnings.warn markers — especially ones without removal versions
  • Version-gated code paths (if version >= X, feature flags, #[cfg(feature = "legacy")])
  • Adapter / shim / bridge / wrapper layers that translate between old and new interfaces
  • Dual serialization formats (v1/v2 JSON schemas, protobuf oneof with legacy fields)
  • Tests that exist solely to validate backward-compatible behavior
  • Configuration keys that toggle between old and new behavior
  • Re-export / forwarding modules that alias old paths to new locations
  • Changelog entries promising deprecation timelines

Decision: Break or Not?

Signal Break Do NOT Break
Zero external consumers Yes
Single internal consumer, you own it Yes
Well-tested, high coverage Yes
Clear new path exists Yes
External/public API with unknown consumers Not without migration plan
No tests covering the boundary Write tests first, then break
Multiple consumers, unclear ownership Map consumers first
Compat layer under active use by migration-in-progress Finish migration first

Execution Strategy

  1. Map blast radius. List every file, module, and external consumer that references the old API. Use ast-grep, rg, or equivalent — not guesswork.
  2. Snapshot current behavior. Ensure tests cover the old path. If coverage is missing, add characterization tests before removal.
  3. Remove the old path. Delete the compat layer, adapter, or legacy code. Do not comment it out.
  4. Update all call sites. Migrate every reference found in step 1 to the new API. Compile/typecheck after each batch.
  5. Delete orphaned tests. Tests that validated the old path are now dead weight. Remove them.
  6. Search for ghosts. Grep for string references, config keys, environment variables, documentation links, and error messages that mention the old API.
  7. Verify no dead imports/deps. Check for unused imports, packages, or dependencies that only the old path required.

Anti-patterns

  • "Just in case" paths — keeping old code "in case someone needs it." That is what version control is for.
  • Partial migration — half the codebase on new API, half on old. Worse than either alone.
  • Commenting out instead of deleting — commented code is invisible debt that greps cannot find.
  • Compat-of-compat — wrapping a compat layer in another compat layer. Two wrongs do not make an abstraction.
  • Deprecated without removal date — a deprecation warning without a deadline is a suggestion, not a plan.
  • Stale feature flags — flags that are always on (or always off) in every environment. Delete the flag, keep the winning path.

Validation Gates

Gate Condition
Blast radius mapped Every consumer of old API identified and listed
Tests green pre-removal Existing tests pass before any deletion begins
Zero references post-removal ast-grep / rg for old API names returns zero hits
No dead imports/deps No unused imports, packages, or type declarations remain

Exit Codes

Code Meaning
0 Clean break — old API fully removed, all consumers migrated, tests pass
1 Partial — old references remain in code, docs, or config
2 Tests broken — removal caused test failures not yet resolved
3 External consumers found — need migration plan before proceeding

Expand your agent's capabilities with these related and highly-rated skills.

OutlineDriven/odin-claude-plugin

pr-merge-temporal

Merge multiple PRs into a temporal integration branch before merging to base, with ordered conflict resolution. Use when you want to validate a set of PRs together on a staging branch before advancing the base branch.

17 0
Explore
OutlineDriven/odin-claude-plugin

tests-adversarial

Write adversarial tests that intentionally stress failure paths. Use when hardening error handling, stress-testing assumptions, validating boundary behavior, or hunting silent failures.

17 0
Explore
OutlineDriven/odin-claude-plugin

srgn-cli

Practical guide for building safe, syntax-aware srgn CLI commands for source-code search and transformation. Use when users ask for srgn commands, scoped refactors (comments/docstrings/imports/functions), multi-file rewrites with --glob, custom tree-sitter query usage, or CI-style checks with --fail-any/--fail-none.

17 0
Explore
OutlineDriven/odin-claude-plugin

askme

Verbalized Sampling (VS) protocol for deep intent exploration before planning. Use when starting ambiguous or complex tasks, when multiple interpretations exist, or when you need to explore diverse intent hypotheses and ask maximum clarifying questions before committing to an approach.

17 0
Explore
OutlineDriven/odin-claude-plugin

pr-merge-base

Merge one or more PRs into the base branch with queue-like sequencing and conflict resolution. Use when merging PRs that may conflict with each other or the base, requiring ordered application and intelligent conflict handling.

17 0
Explore
OutlineDriven/odin-claude-plugin

gh-fix-ci

Inspect GitHub PR checks with gh, pull failing GitHub Actions logs, summarize failure context, then create a fix plan and implement after user approval. Use when a user asks to debug or fix failing PR CI/CD checks on GitHub Actions and wants a plan + code changes; for external checks (e.g., Buildkite), only report the details URL and mark them out of scope.

17 0
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results