bdd-specification/SKILL.md is the strict default for "any change that adds or
changes observable behaviour — new features, behavioural enhancements, and
behaviour-changing bug fixes", and implement-issue-workflow/SKILL.md invokes it
at implementation time. "The only way out is an explicit, recorded human waiver.
Do not skip the specification on your own judgement."
That rule has no answer for a defect whose observable behaviour lives below the
layer the scenario bridge attaches to. Following it literally produces a scenario
that passes before and after the fix.
The case that produced this
A consuming project fixed a defect where a category named Gesundheit / Arzt Dieter could not be updated or deleted. The name addressed the resource through
a URL path segment, and Tomcat rejects the %2F it percent-encodes to with a 400
before any handler is chosen.
Observable behaviour, plainly: the owner could not edit those categories in the
running application. So the strict default applies.
But that project's .feature steps drive the use-case ports directly — which is
the arrangement the skill's own abstraction-level guidance encourages, since a
scenario "describes observable business or system behaviour" rather than a
transport. The domain always accepted a name containing a slash. A scenario
reading
Scenario: A category whose name contains a slash can be moved to another group
Given the category group "Gesundheit / Arzt"
And the category "Gesundheit / Arzt Dieter" in "ungrouped"
When I move "Gesundheit / Arzt Dieter" to "Gesundheit / Arzt"
Then the category "Gesundheit / Arzt Dieter" is in group "Gesundheit / Arzt"
is green against the broken code. The defect is unreachable from the layer the
bridge is bound to.
The verification that does catch it asserts a 400 against a real servlet
container — a statement about HTTP, which is exactly what the skill tells authors
to keep out of feature files ("Keep the feature files as Living Documentation,
not as technical test catalogues written in Gherkin").
Why this is a method gap rather than a project mistake
The two rules are individually right and jointly leave a hole:
- Scenarios describe business behaviour, not technical decomposition — so the
bridge attaches at the domain or use-case layer.
- Every behaviour-changing bug fix needs a scenario — including defects that
exist only in the adapter above that layer.
Where they meet, the skill asks for a scenario that cannot fail. That is a guard
with no failure path, and adding one is worse than adding none: the feature file
grows a line that reads like coverage of a defect it never touched.
The waiver clause does not close it either. A waiver is a human decision about
proportionality — "this is too small to specify". This is not that. The
specification is not disproportionate; it is not expressible at the bridge layer
at all, and no amount of human authority changes that.
What might close it
Not a proposal, since the shape is the maintainers' call — but the missing
sentence is roughly: before writing the scenario, check that it can fail against
the unfixed code. If it cannot, the behaviour is not specifiable at the bridge
layer, and the change needs a test at the layer that owns the defect plus a note
saying so — rather than a scenario that is green either way.
That check is cheap and mechanical: run the new scenario against the code before
the fix. It also generalises past this case, because it is the same discipline
the bridge convention already relies on to mean anything.
References
bdd-specification/SKILL.mdis the strict default for "any change that adds orchanges observable behaviour — new features, behavioural enhancements, and
behaviour-changing bug fixes", and
implement-issue-workflow/SKILL.mdinvokes itat implementation time. "The only way out is an explicit, recorded human waiver.
Do not skip the specification on your own judgement."
That rule has no answer for a defect whose observable behaviour lives below the
layer the scenario bridge attaches to. Following it literally produces a scenario
that passes before and after the fix.
The case that produced this
A consuming project fixed a defect where a category named
Gesundheit / Arzt Dietercould not be updated or deleted. The name addressed the resource througha URL path segment, and Tomcat rejects the
%2Fit percent-encodes to with a 400before any handler is chosen.
Observable behaviour, plainly: the owner could not edit those categories in the
running application. So the strict default applies.
But that project's
.featuresteps drive the use-case ports directly — which isthe arrangement the skill's own abstraction-level guidance encourages, since a
scenario "describes observable business or system behaviour" rather than a
transport. The domain always accepted a name containing a slash. A scenario
reading
is green against the broken code. The defect is unreachable from the layer the
bridge is bound to.
The verification that does catch it asserts a 400 against a real servlet
container — a statement about HTTP, which is exactly what the skill tells authors
to keep out of feature files ("Keep the feature files as Living Documentation,
not as technical test catalogues written in Gherkin").
Why this is a method gap rather than a project mistake
The two rules are individually right and jointly leave a hole:
bridge attaches at the domain or use-case layer.
exist only in the adapter above that layer.
Where they meet, the skill asks for a scenario that cannot fail. That is a guard
with no failure path, and adding one is worse than adding none: the feature file
grows a line that reads like coverage of a defect it never touched.
The waiver clause does not close it either. A waiver is a human decision about
proportionality — "this is too small to specify". This is not that. The
specification is not disproportionate; it is not expressible at the bridge layer
at all, and no amount of human authority changes that.
What might close it
Not a proposal, since the shape is the maintainers' call — but the missing
sentence is roughly: before writing the scenario, check that it can fail against
the unfixed code. If it cannot, the behaviour is not specifiable at the bridge
layer, and the change needs a test at the layer that owns the defect plus a note
saying so — rather than a scenario that is green either way.
That check is cheap and mechanical: run the new scenario against the code before
the fix. It also generalises past this case, because it is the same discipline
the bridge convention already relies on to mean anything.
References
measurements and the four-case regression test:
Edit a
Categorywhose name contains a slash dieterbaier/budget#82 andissue_82: Address a category by a name that contains a slash dieterbaier/budget#83