Acceptance Criteria That Can Fail on Your Laptop
A spec line is only finished when something can fail it. Most of the lines can be checked where you already work.
A spec line is only finished when something can fail it. Most of the lines can be checked where you already work.
Spec-driven development is good at saying what should be true. It is silent on how you will find out that it is not. That gap is where tidy specs turn into quiet lies.
A criterion with no failing path is a wish
Take the line the service is ready to accept orders. Read it as a reviewer and it sounds finished. Read it as a test and it is empty: ready according to whom, checked how, and what happens when it is false?
The fix is not a longer spec. It is attaching each line to something that can go red on the machine where the work happens.
Four checks that already exist
A Flisk stack gives you most of these without writing a test framework:
- Liveness and readiness. A service declares
healthCheckPath, and a check can be a path, an open TCP port, or a command that must exit 0. "Ready to accept orders" becomes a URL that returns 200 only when the dependencies it needs are reachable. - Status as data.
flisk status --jsonreports readiness per resource, so a script, a reviewer or an assistant can assert on it instead of reading a screenshot. - Ordering that is enforced. A service that depends on a migrator starts only after the migration job exited 0, and the services after a failed job are not started. "Schema exists before the API serves traffic" stops being a sentence and becomes behavior.
- Generated files match intent.
flisk config verify --jsonfails when the generated files drift from.flisk/project.jsonor aservice.jsonis invalid.
Write the criterion and the check together
When you add an acceptance line, add the command next to it. For example:
Criterion: orders API is ready only when the database is reachable.
Check: flisk status --json (orders-api: ready)
Break it: stop the database container, expect orders-api not ready
The last line matters most. A check that has never been seen to fail proves nothing. Break the dependency on purpose once, watch the check go red, and you know the criterion is real.
What this does not replace
Local checks do not prove production behavior, and they do not replace product judgment about whether the criterion was the right one. They remove the cheapest failure: a spec that was never run against anything. Everything else the spec still has to earn.