characterize
Skill2 starsChanged 5 months agoMITView on GitHub
Write characterization (approval/golden-master) tests that pin the CURRENT behavior of untested legacy code BEFORE it is changed. The "no tests = no writes" safety net for brownfield adoption — distinct from tdd-loop (which drives NEW behavior red→green). Use during /adopt Phase 4, or whenever a task must touch a file flagged in .claude/state/adopt/uncharacterized-paths.txt.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- AJschoons/robowrighttheir own version, first seen Nov 8, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- AJschoons/robowright★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository60 other files it gives its agents.
- .claude/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- analyzeSkill
- animation-disciplineSkill
- api-versioningSkill
- autopilotSkill
- browser-e2eSkill
- clarifySkill
- codemodSkill
- constitution-compactSkill
- constitutionSkill
- context-budgetSkill
- creative-webSkill
- db-migrationSkill
- debugSkill
- detect-stackSkill
- dispatch-criteriaSkill
- dreamSkill
- experimentSkill
- fastapiSkill
- flag-cleanupSkill
- flag-rolloutSkill
- flask-realtimeSkill
- framework-detectorSkill
- front-end-designSkill
- grill-meSkill
- handoffSkill
- image-generationSkill
- implementSkill
- initiativeSkill
- instinctSkill
- loopSkill
- nextjsSkill
- observabilitySkill
- okr-alignSkill
- parallel-swarmSkill
- pivotSkill
- planSkill
- pr-bodySkill
- prime-disciplineSkill
- prod-observabilitySkill
- react-nodeSkill
- react-viteSkill
- release-trainSkill
- researchSkill
- reviewSkill
- security-guardSkill
- self-healSkill
- shipSkill
- skill-creatorSkill
- specifySkill
- tailwind-disciplineSkill
- tasksSkill
- tdd-loopSkill
- token-budgetSkill
- typographySkill
- verify-loopSkill
- verifySkill
- wip-checkpointSkill
- <kebab-case-skill-name>Skill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 4 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
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
- Distinctive: line 31
Capture current output (the golden master): Run the code against representative inputs (include real production-shaped data + edge cases …
- Very specific: line 40
Record the ledger: Write verify/<date>/<task>/green.log (it passed) so the TDD-ledger gate is satisfied.
- Distinctive: line 52
If the task ADDS behavior (not modifies), use Feathers' Sprout Method/Class: write the new logic in a fresh, fully-TDD'd function/class and …
- Distinctive: line 61
Document reality, including bugs: If the legacy code returns the wrong total, the characterization test asserts the wrong total.
- Distinctive: line 64
Smallest seam: Don't refactor broadly to make code testable.
≈ “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.
Files
Characterize
Pin what the code does today — not what it should do — so you can change it without silently breaking it. From Michael Feathers, Working Effectively with Legacy Code: a characterization test documents existing behavior; you write it, THEN change the code, and the test tells you if you altered behavior you didn't mean to.
This is the inverse of tdd-loop:
| tdd-loop | characterize | |
| Goal | drive NEW behavior | freeze EXISTING behavior |
| "red" means | the feature isn't built yet | (n/a — there was no test) |
| Oracle | the spec's acceptance criteria | the code's current output |
| When | greenfield / new feature | brownfield / untested legacy |
The loop
- Find a seam. Identify where you can observe the code's output without changing it — a pure function's return, an HTTP handler's response, a CLI's stdout, a rendered DOM. If there's no seam, introduce the minimum one (extract a function, inject a dependency) — that itself is a behavior-preserving refactor; do it tiny and commit separately.
- Capture current output (the golden master). Run the code against representative inputs (include real production-shaped data + edge cases from the hotspots list). Record exactly what it returns/emits — bugs included. You are documenting reality, not correctness.
- Write the test asserting that captured output. Name it so the gate recognizes it:
<name>.characterization.test.<ext>(JS/TS) ortest_<name>_characterization.py(Python), co-located or under the repo's test root. Use the repo's existing test runner (seeAGENTS.md/ atlas). - Run it — it must PASS immediately (it asserts what the code already does). A failing characterization test means your captured oracle is wrong; fix the capture, not the code.
- Record the ledger. Write
verify/<date>/<task>/green.log(it passed) so the TDD-ledger gate is satisfied. There is nored.logrequirement for characterization — note "characterization (no prior test)" in the task instead. - Now you may change the code. Make your change; re-run the characterization test. If it fails, you changed observable behavior — decide deliberately: update the golden master (with a one-line rationale) or revert.
- Remove the path from the manifest. Once a flagged-legacy file has a characterization test,
delete its glob (or the file) from
.claude/state/adopt/uncharacterized-paths.txtso autopilot andverify.shstop blocking it.
For NEW features in untested legacy: sprout, don't touch
If the task ADDS behavior (not modifies), use Feathers' Sprout Method/Class: write the new
logic in a fresh, fully-TDD'd function/class and call it from the legacy code with the smallest
possible edit. The legacy body stays untouched — so you never owe it a characterization test, and
the new code gets normal tdd-loop red→green rigor.
Hard rules
- Characterize before you change. No tests = no writes (verify.sh enforces;
SKIP_CHAR_GATE=1is a human-only override, never an autopilot one). - Document reality, including bugs. If the legacy code returns the wrong total, the characterization test asserts the wrong total. Fixing the bug is a separate, later task with its own spec — now made safe because the test will flag the behavior change.
- Smallest seam. Don't refactor broadly to make code testable; introduce the minimum seam, commit it alone, then characterize.
- Hotspots first. Characterize the churn×LOC hotspots from
ADOPTION-REPORT.mdbefore the long tail — that's where factory-driven change is most likely and most dangerous.
References
- Michael Feathers, Working Effectively with Legacy Code (characterization tests, seams, sprout/wrap)
docs/research/brownfield-onboarding.md(the adoption research brief).claude/skills/tdd-loop/SKILL.md(the greenfield counterpart).claude/commands/adopt.md(Phase 4 invokes this)
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
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.

