aboutsummaryrefslogtreecommitdiff
path: root/.ai/workflows
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-19 19:51:51 -0500
committerCraig Jennings <c@cjennings.net>2026-07-19 19:51:51 -0500
commit179c495fa7fcb2c2dcf7bdb81b1459afaa0e5075 (patch)
treedc2fe80817af1f447575ce8d0092d9370c7a29e1 /.ai/workflows
parenta760d8e2e645000deb56b4a0a7d922147b2b1ad7 (diff)
downloadrulesets-179c495fa7fcb2c2dcf7bdb81b1459afaa0e5075.tar.gz
rulesets-179c495fa7fcb2c2dcf7bdb81b1459afaa0e5075.zip
docs(testing): sharpen characterization-test guidance, wire it into the quality sweep
The rule already said "write a characterization test before refactoring" but not what one is or how many to write per unit. Two additions close that. testing.md's "Adding Tests to Existing Untested Code" now defines a characterization test as recording what the code actually does, not what it should (Feathers' assert-wrong-read-the-real-value recipe), and requires the same Normal/Boundary/Error set as any unit rather than one happy-path capture. The reason is the useful part: on a characterization test the negative and boundary cases are the bug-finders, because untested legacy code is weakest at the empty input and the missing upstream, and pinning what it currently does there writes the wrong behavior down where it becomes a visible bug. A pinned case that turns out to be a bug graduates from recording current behavior to asserting correct behavior. In-unit bugs fall to this set. Composition bugs need a functional test. The refactor-for-testability section gains the framing that when the untestable code is legacy you're hardening, extracting the pure core is the hardening, not a detour around it. A function you can't characterize without mocking tmux or git can't be refactored safely, so "needs too much mocking" is the signal to reshape it, never a license to skip the boundary and error cases. code-quality.org's passes claim to preserve behavior, so it now states the precondition that makes that true: on untested scope, a characterization net comes first, or "behavior-preserving" is an assertion the green suite can't actually verify.
Diffstat (limited to '.ai/workflows')
-rw-r--r--.ai/workflows/code-quality.org7
1 files changed, 7 insertions, 0 deletions
diff --git a/.ai/workflows/code-quality.org b/.ai/workflows/code-quality.org
index 3ac3e9d..0481166 100644
--- a/.ai/workflows/code-quality.org
+++ b/.ai/workflows/code-quality.org
@@ -9,6 +9,13 @@ One trigger that runs every behavior-preserving quality pass over a scope of
orchestrator — each pass keeps its own discipline and its own confirm gate; this
workflow only sequences them and collects the residue.
+*Behavior-preserving rests on a test net.* The passes below claim to preserve
+behavior, but a refactor on untested code is a guess, not a preservation. Where
+the scope has no tests, bring it under a characterization net first
+(Normal/Boundary/Error per unit, per =testing.md='s "Adding Tests to Existing
+Untested Code") — that net is what turns "behavior-preserving" from an assertion
+into something the green suite actually verifies across each pass.
+
The passes it chains:
1. =/refactor= — structural and logic cleanup on measurable metrics (complexity,