Teach QA and the BA two rules, both harvested from live failures - #21
Open
patelanil wants to merge 2 commits into
Open
Teach QA and the BA two rules, both harvested from live failures#21patelanil wants to merge 2 commits into
patelanil wants to merge 2 commits into
Conversation
Both rules were harvested from a live failure, not invented. QA - the premise question. Asked to review a test-harness spec, QA reviewed the mechanics thoroughly and never asked where the expected outcomes came from. They came from the code under test. Such a suite cannot fail when the code is wrong; it asserts that the code does what it does. The failure is invisible from inside the test - coverage looks high, assertions look specific, and none of it can ever disagree with the implementation. QA now asks 'how do we know the code did what it should have done?' before reviewing anything, traces every expected outcome to its origin, and rejects three shapes of circularity outright: expectations recorded from a run, coverage measured by diffing code against tests, and an expected outcome justified by a code citation instead of a rule or a person. BA - specification recovery. Writing requirements for a system that already exists is legitimate and common, but reading working code and writing down what it does produces something that looks like a spec and can never disagree with the implementation. Working code is evidence, never a requirement: it proves a behaviour exists, not that anyone wanted it. Five rules - elicit before reading, tag every statement with its provenance, treat unowned behaviour as a finding, separate configuration from requirement, and leave silence silent rather than filling it from code. Give-away test: if a business person could not have drawn the distinction unprompted, it came from the code.
Second rule harvested from a live failure, alongside the premise question. A whole class of finding takes the form 'X does not exist' - a seed row, a status, a service, a guard. Every factual link can be correct and the finding still be wrong, because a missing thing and a deliberately absent thing look identical in a grep. The worked example is real and is included in the agent file. A sweep reported that a status transition was not seeded and the framework therefore throws. Verified six ways: absent from seed data, absent from upgrade data, absent in a second checkout at a different version, no other component seeds it, the framework does throw, no service overrides it. Every link held. The finding was still wrong. The seed data modelled a four-step physical return lifecycle - requested, accepted, received, completed - and recorded that order in a field the framework never reads. The transition was missing because it would let a return complete without the goods ever arriving. The framework was not failing, it was defending the model. The defect was in the code that skipped the ladder, and a sibling flow already walked it correctly. Seeding the row would have silenced the exception and deleted the control. So QA now asks, before reporting any absence, whether it is absent by accident or on purpose - looking for ordering fields, a sibling path that honours the constraint, and what the absence prevents - and then checks the remedy it is implying, because a finding phrased as 'X is missing' tells the reader to add X. Also adds reachability: trace callers before reporting, and label unreachable findings LATENT. A confident defect report about dead code costs the reader real time and teaches them to discount the next one. Proving that a failure happens is not the same as proving it is a bug.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two agent files, +142 lines. No behaviour changes elsewhere.
Both rules came out of a real specification-recovery engagement where the agents — and I — got things wrong in ways that looked like success. Each rule carries the worked example that produced it, because the lesson does not land without the detail.
1. QA — the premise question
Asked to review a test-harness spec, QA reviewed the mechanics thoroughly and never asked where the expected outcomes came from. They came from the code under test.
Such a suite cannot fail when the code is wrong. It asserts that the code does what it does. The failure is invisible from inside the test — coverage looks high, assertions look specific, and none of it can ever disagree with the implementation.
QA now asks, before reviewing anything:
Then traces every expected outcome to its origin. From a requirement, a design document, or a named person: legitimate. From the code, its output, or a database that code populated: circular, reject it.
Three shapes of the same mistake are named explicitly, because only the first is obvious:
2. QA — the absence question
A sweep reported that a status transition was missing from seed data and the framework therefore throws. It was verified six ways — absent from seed data, absent from upgrade data, absent in a second checkout at a different version, no other component seeds it, the framework does throw, no service overrides it. Every link held.
The finding was still wrong.
The seed data modelled a four-step physical return lifecycle — requested, accepted, received, completed — and recorded that order in a field the framework never reads. The transition was missing because it would let a return complete without the goods ever arriving. The framework was not failing; it was defending the model. The defect was in the code that skipped the ladder, and a sibling flow already walked it correctly.
Seeding the row would have silenced the exception and deleted the control.
So QA now asks, before reporting any absence, whether it is absent by accident or on purpose — looking for ordering fields, a sibling path that honours the constraint, and what the absence prevents. Then it checks the remedy it is implying, because a finding phrased as "X is missing" tells the reader to add X.
Also adds reachability: trace callers before reporting, and label unreachable findings LATENT. A confident defect report about dead code costs the reader real time and teaches them to discount the next one.
3. BA — specification recovery
Writing requirements for a system that already exists is legitimate and common. Reading the working code to do it produces a document that looks exactly like a specification and can never disagree with the implementation.
Working code is evidence, never a requirement. It proves a behaviour exists, not that anyone wanted it — and a long-running system accumulates behaviours nobody asked for.
Five rules: elicit before reading, tag every statement with its provenance, treat unowned behaviour as a finding rather than promoting it, separate configuration from requirement, and leave silence silent rather than filling it from code.
With a give-away test for self-checking: if a business person could not have drawn the distinction unprompted, it came from the code.
Evidence these work
The same engagement re-verified 26 findings adversarially under these rules. About half were wrong in a way that changed the action — three refuted outright, twelve reframed, two understated. The absence rule alone caught two cases of code inventing a status the data model deliberately does not have.