skills/welc-legacy-code/SKILL.md
Use when facing untested legacy code, test harness problems, dependency issues, or time pressure. Triggers on: legacy code, no tests, can't test, afraid to change, need to modify untested code.
npx skillsauth add ryanthedev/code-foundations welc-legacy-codeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
"Legacy code is simply code without tests." - Michael Feathers
Get code under test before changing it. This is the core principle.
| Symptom | Solution | |---------|----------| | Can't get class into test harness | Decision Tree: Can't Instantiate | | Can't run method in test harness | Decision Tree: Can't Call Method | | Don't know what tests to write | Characterization Tests | | Under time pressure, need to change now | Sprout/Wrap Techniques | | Need to change many classes in one area | Pinch Point Testing | | Class is too big / monster method | Effect Sketching → find clusters | | Afraid I'll break something | Single-Goal Editing, Preserve Signatures |
Use this for every change to untested code.
1. IDENTIFY change points
- Where in the code do you need to make modifications?
2. FIND test points
- Where can you write tests to cover the change?
- Look for pinch points where tests cover multiple changes
3. BREAK dependencies
- Remove obstacles that prevent testing
- Use dependency-breaking techniques (catalog below)
4. WRITE characterization tests
- Document what the code DOES, not what it SHOULD do
- Process: write assertion you know will fail → let failure
tell you actual behavior → change test to match
5. MAKE changes and refactor
- Implement the change with test safety net
When you can't test everything but need to change code now:
These keep new code separate and testable even when old code isn't.
When you don't know what tests to write:
You're documenting what the code does, not what it should do. This is the test safety net for refactoring.
When you need to change many classes in one area:
| Technique | When to Use | |-----------|-------------| | Adapt Parameter | Parameter class hard to fake | | Break Out Method Object | Long method with local state | | Encapsulate Global References | Global variables block testing | | Expose Static Method | Method uses no instance state | | Extract and Override Call | Single problematic call | | Extract and Override Factory Method | Constructor creates dependencies | | Extract and Override Getter | Instance variable holds problem | | Extract Implementer | Turn class into interface | | Extract Interface | Need to fake a class | | Introduce Instance Delegator | Static method blocks testing | | Introduce Static Setter | Singleton blocks testing | | Parameterize Constructor | Constructor creates its dependencies | | Parameterize Method | Method obtains dependency internally | | Primitivize Parameter | Parameter hard to create, only data needed | | Pull Up Feature | Test feature in isolation | | Push Down Dependency | Separate testable logic from dependencies | | Replace Global Reference with Getter | Global variable access | | Subclass and Override Method | Method behavior blocks testing | | Supersede Instance Variable | Replace after construction |
Is the problem in the constructor?
├── YES: Does constructor CREATE objects?
│ ├── YES: Parameterize Constructor or Extract and Override Factory Method
│ └── NO: Does constructor USE passed objects?
│ ├── YES: Extract Interface on parameter, pass fake
│ └── NO: Hidden dependency — find the `new` and externalize it
└── NO: Is it a singleton/global?
├── YES: Introduce Static Setter
└── NO: Include/import dependency chain
└── Extract Interface or Extract Implementer
Is the method private?
├── YES: Make protected, create testing subclass
└── NO: Is a parameter hard to create?
├── YES: Is parameter sealed/final?
│ ├── YES: Adapt Parameter
│ └── NO: Extract Interface from parameter
└── NO: Does method have invisible side effects?
└── YES: Extract side effects to separate methods, override in test
Can you test the new code in isolation?
├── YES: Sprout Method or Sprout Class
└── NO: Does new behavior go before/after existing?
├── YES: Wrap Method
└── NO: Can you not modify the class at all?
└── YES: Wrap Class (Decorator)
| After | Next | |-------|------| | Code under test | cc-refactoring-guidance (safe refactoring process) | | Dependencies broken | Continue with Legacy Code Change Algorithm step 4-5 |
testing
Standard/Full planning pipeline for plan command. Steps: discover, classify, explore, detail, save, check, confirm, handoff. Use when dispatched from plan command for Medium/Complex tasks. Triggers on 'planning pipeline', 'standard track', 'full track'.
development
Generate or update docs/code-standards.md by scanning codebase conventions. Produces example-rich standards that help LLMs write consistent code. Use when starting a planning or build task. Triggers on 'code standards', 'codebase scan', 'scan conventions'.
development
--- name: performance-optimization description: Use when code is too slow, has performance issues, timeouts, OOM errors, high CPU/memory, or doesn't scale. Triggers on: profiler hot spots, latency complaints, needs optimization, critical path analysis. --- # Skill: performance-optimization ## STOP - Measure First (MANDATORY GATE) **Do not optimize based on intuition -- profile first.** - **Correctness before speed** -- make it work, then make it fast - **<4% of code causes >50% of runtime**
testing
Decompose user intent through structured brainstorming. Detects underspecification, ambiguity, and false premises through hypothesis-driven questioning. Use when a request is unclear, could have multiple valid interpretations, or critical details are missing.