Skip to content
Skills Library
Programming · Building & coding

legacy-code-changes

/legacy-code-changes

Change untested legacy code safely using characterization tests, seams, and the sprout method. Use when you must modify code that has no tests and you cannot prove your change is harmless.

Repository
AI-SKILLS ↗
Licence
MIT
Last repository change
05.09.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 05.09.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Change untested legacy code safely using characterization tests, seams, and the sprout method. Use when you must modify code that has no tests and you cannot prove your change is harmless.

Original author description

Change untested legacy code safely using characterization tests, seams, and the sprout method. Use when you must modify code that has no tests and you cannot prove your change is harmless.

How it works

  1. Method
  2. Signals
  3. Boundaries
Original SKILL.md headings · 47 lines, 395 words
SKILL.md preview
---
name: legacy-code-changes
description: Change untested legacy code safely using characterization tests, seams, and the sprout method. Use when you must modify code that has no tests and you cannot prove your change is harmless.
---

# Legacy code changes

Legacy code is code without tests, so you cannot change it and know you did
no harm. The instinct to rewrite is usually a trap: the safe path is to pin
the current behavior first, then make the smallest possible cut. Michael
Feathers named these moves, and they still hold.

## Method

1. **Characterize before you change.** Write tests that capture what the code
   does now, not what it should do. Feed it real inputs and assert the actual
   outputs, including the ugly ones. These tests document reality and turn a
   silent behavior change into a red bar.
2. **Find a seam to test at.** A seam is a place you can alter behavior
   without editing the code in question: a function argument, a subclass
   override, an injected dependency. Break a hidden `new Clock()` or global
   read into a parameter so the code becomes testable at all.
3. **Sprout new code, do not edit in place.** Write the new behavior in a
   fresh, fully tested method or class, then call it from one line in the old
   code. The tangle stays untouched while your addition is clean and covered.
4. **Wrap when new work must bracket the old path.** If behavior must happen
   before or after existing logic, rename the old method and have a new
   method of the old name call the original plus your addition. The old body
   moves unchanged.
5. **Cut the smallest hole.** Change the fewest lines that close the ticket.
   Every extra line touched in untested code is a bet with no test to
   collect on. Resist tidying the surrounding mess in this change.
6. **Bank the tests as coverage.** Keep the characterization tests after the
   change. They are now the safety net the next person lacked, converting
   this file from legacy to merely old.

## Signals

- If your change altered behavior by accident, would a characterization test
  go red?
- Did the new logic land in a tested unit rather than deep inside the
  untested block?
- Is the diff the minimum that closes the ticket?

## Boundaries

When a module is small, dead, or slated for deletion, a full characterization
suite can cost more than a careful rewrite: use judgment. This skill covers
making one change safely, not deciding whether to retire the system. For
staged replacement of a whole system, see strangler-fig.

Versions

The database has no other skills named legacy-code-changes.

Database snapshot: 13.11.2026 · package version ae12e6c5ea08 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100working-with-legacy-code
    Safely change and test untested codebases using Feathers'' "Working Effectively with Legacy Code". Use when the user mentions "legacy code", "no tests", "untested codebase", "how do I test this", "seams", "characterization tests", "golden master", "sprout method", "afraid to…
  • 90design-legacy-seams
    Get legacy code under test before changing it — find seams, write characterization tests. Use when changing untested code, breaking dependencies, or taming legacy.
  • 100legacy-code
    Safely modify code that lacks tests. Use whenever tasked with changing code without test coverage — apply characterization tests and dependency-breaking techniques before making any behavioral changes.
  • 100legacy-code-refactoring-characterization-tests
    Use this skill when harness untracked legacy code with automated characterization tests before refactoring.
  • 100legacy-refactoring
    Changes legacy or untested code safely by pinning current behavior with characterization tests, finding seams to break dependencies, and refactoring in small behavior-preserving steps that keep the build green. Use when modifying code that has no tests, cleaning up a large class…
  • 90legacy-code-testing
    Adds tests to legacy code that has none, safely: characterization tests that pin current behavior (including bugs) before any refactoring, seam identification for breaking untestable dependencies, and a risk-ranked coverage strategy. Use for untested or inherited codebases.…

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.