smithery.ai

code-migration

Use when moving logic between layers, deprecating patterns, refactoring responsibilities, or enforcing canonical owners. Ensures migrations are complete with no legacy coexistence.

First seen Apr 15, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,960 B
  • docs SUMMARY.md 202 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Code Migration

Core principle: When you move responsibility from A to B, delete A.

Half-migrations are technical debt. If fileshelper.py and pathcomp.py both construct paths, every developer must learn which one to use. That ambiguity is the bug.


Migration Checklist

When moving logic from one location to another:

  • Move the code to its canonical location
  • Update all call sites (use grep, not hope)
  • Update skills that reference the old location
  • Add ruff rules to ban imports from the old location
  • Delete the old code (not deprecate - delete)
  • Run validate_skills.py to catch stale references
  • Run tests to confirm nothing broke

If you can't check all boxes, the migration isn't done.


Canonical Owners

Every responsibility has exactly ONE canonical owner:

Responsibility Canonical Owner NOT
Library path construction path_comp.py files_helper.py
Wall-clock timestamps timehelper.nowms() time.time()
Monotonic intervals timehelper.internalms() time.monotonic()
Essentia calls mlbackendessentia_comp.py anywhere else
Logging setup logginghelper.getlogger() logging.getLogger()
Config access Injected AppConfig os.environ, config.yaml

If two places can do the same thing, one of them is wrong.


Enforcement Stack

Migrations are enforced at every layer:

1. Ruff Rules (Syntax-Level)

Ban dangerous imports before code runs:

# ruff.toml
[lint.flake8-tidy-imports.banned-api]
"time.time".msg = "Use nomarr.helpers.time_helper.now_ms() for timestamps"
"builtins.print".msg = "Use logging via get_logger()"

2. Import-Linter (Architecture-Level)

Prevent layer violations:

helpers cannot import from services
workflows cannot import from interfaces
only ml_backend_essentia_comp.py may import essentia

3. Skills (Documentation-Level)

Every skill documents what IS canonical, not what WAS.

4. validate_skills.py (Tooling-Level)

Catches stale references in skills:

python scripts/validate_skills.py --check-refs

Anti-Patterns

Deprecation Warnings

# ❌ Wrong - deprecation is procrastination
import warnings
warnings.warn("Use path_comp instead", DeprecationWarning)

If it's deprecated, delete it. Pre-alpha means no backwards compatibility.

Keeping It Around Just In Case

# ❌ Wrong - dead code that looks alive
def old_path_builder(path: str) -> str:
    """DEPRECATED: Use path_comp.build_library_path_from_input()"""
    ...

Delete it. Git remembers.

TODO: Remove After Migration

# ❌ Wrong - TODOs are lies
# TODO: Remove this once all callers use the new API
def legacy_function():
    ...

Remove it now. The migration isn't done until it's gone.

Wrapper For Compatibility

# ❌ Wrong - shims become permanent
def get_path(path: str) -> str:
    """Compatibility wrapper."""
    return path_comp.build_library_path_from_input(path).absolute

Update the callers directly.


Migration Workflow

Step 1: Identify the Migration

# Find all usages of the old pattern
python scripts/discover_import_chains.py nomarr.helpers.files_helper

# Or grep for specific functions
grep -r "build_path" nomarr/

Step 2: Create the Canonical Location

Move the logic to its proper layer (components for business logic, helpers for pure utilities).

Step 3: Update All Call Sites

# Find all files that import the old module
grep -r "from nomarr.helpers.files_helper import" nomarr/

Step 4: Ban the Old Pattern (If Still Exists)

If old code still exists and has callers, add a temporary ruff ban to prevent new usages:

# Add to ruff.toml during migration
[lint.flake8-tidy-imports.banned-api]
"nomarr.helpers.files_helper.build_path".msg = "Use path_comp.build_library_path_from_input()"

Remove the ban after deleting the old code. Bans for deleted patterns are garbage.

Step 5: Delete the Old Code

git rm nomarr/helpers/old_module.py

Step 6: Update Skills

python scripts/validate_skills.py --check-refs

Step 7: Verify Migration Complete

# Check that all traces are gone
python scripts/check_migration.py nomarr.helpers.old_module

# If migration plan included a ruff ban, verify it exists
python scripts/check_migration.py nomarr.helpers.old_module --expect-ban

# Full QC
python scripts/run_qc.py
pytest

Decision Framework

When you find duplicate responsibilities:

Q: Is there a clear canonical owner?
├─ No  → Decide which location should own it
└─ Yes → Q: Does the old location still exist?
         ├─ Yes → Delete it. Update callers first if needed.
         └─ No  → Good. Verify skills and rules match reality.

When someone proposes keeping both:

"Can we keep the old one for compatibility?"
→ No. Pre-alpha. Delete it.

"What if something still uses it?"
→ Find it and update it. That's the migration.

"What if we need it later?"
→ Git remembers. Delete it.

Validation

Before considering a migration complete, run:

python scripts/check_migration.py nomarr.old.pattern

The script validates:

  • Old code is deleted, not deprecated
  • No imports of the old module remain
  • No skill references to old pattern
  • No # TODO: remove comments remain
  • (With --expect-ban) Ruff ban exists

Manual checks:

  • No wrapper/shim functions exist
  • Tests pass

The migration is done when there's no trace of the old pattern.