bdd-specs · git:20261014.eeefa6a · 2026-10-14 · sha256 aaafeaf4328dc2f0
bdd-specs git:20261014.eeefa6aA
Immutable. This exact content never changes and is served at /api/v1/blob/aaafeaf4328dc2f0.
--- name: bdd-specs description: >- Writes behavior-driven executable specs from a feature's STORIES.md and PLAN.md, structured as Feature > Scenario > Specification with exactly one logical assertion per test, using whichever test framework the project already has. Covers both layers a feature might touch — C# and Lit/TypeScript, in this skill's references/ files — the discipline is identical, only the syntax differs. Use when a feature's design and stories are finalized and it's time to turn them into a test suite, or when asked to "spec out," "write the tests first," or do BDD/TDD for an Umbraco feature. Dispatched by feature-plan; stops and asks if the design or stories don't exist yet. --- # BDD specs Specs are written before the `builder` subagent implements a task — see "Open question" below if your team wants to relax that. The spec is the design artifact: it encodes the intended behavior from the stories, fails (or is marked pending) first, and is `feature-build`'s definition of done for the task. This skill states the discipline once and applies it to whichever layer(s) a feature actually touches — backend (C#), frontend (Lit + TypeScript), or both. The shape (Feature > Scenario > Specification, one assertion, happy-then-sad, pending by default, a real-entry-point spec) is identical either way; only the syntax it's expressed in differs. Don't duplicate this discipline into a second, stack-specific skill — extend the relevant reference file instead. ## 🎯 Why: Design for Change One assertion per Specification means a failing spec names exactly what broke. Segregating happy path from sad path means you can change one behavior without re-reading the whole suite. The spec suite is the change-budget for the codebase — treat generating it as seriously as generating the code it will gate. ## Gate: require the design and the stories first Read the feature's plan folder. 1. **`SPEC.md`** — if it's missing, still a stub, or full of `TODO`, **stop**. Tell the user: "No design yet — run `feature-design` first, so specs are grounded in real extension points and API shapes instead of invented ones." 2. **`STORIES.md`** — if it's missing, empty, or full of placeholder text, **stop**. Tell the user: "No stories yet — run `feature-plan` first, so specs come from real acceptance criteria instead of invented ones." Do not draft design or stories yourself under this skill — that's `feature-design`'s and `user-stories`'s job. If both gates pass, proceed. ## Which layer(s) does this feature touch? Check `SPEC.md`'s "Management API surface" and "Frontend components" sections, and read only the reference file(s) that layer needs: - **Management API surface isn't "none"** → read `references/backend-csharp.md`. - **Frontend components isn't "none"** → read `references/frontend-lit.md`. - Both present → read both, and generate both as separate spec files in their respective projects. A story that spans both layers gets a spec in each — don't try to force one file to cover both. ## Hard rules (apply to every spec, either layer) 1. **Happy path first, and exhaustive.** Cover every success outcome the story implies before any failure case. 2. **Sad path is segregated** into its own scenario grouping, never interleaved with happy-path specs. 3. **Exactly one assertion per test.** No multiple assertion calls in one test, no looped assertions across a collection — assert on the collection shape instead (a single-item or count check), or split into one test per element being checked. 4. **At least one spec per feature exercises the real entry point** — for a backend story, a Management API controller action through an in-memory test server, or a service resolved from DI exactly as Umbraco's Composer would wire it up; for a frontend story, the actual custom element rendered and driven through its public attributes/properties/events, not an internal method called directly. Fakes/mocks are fine for collaborators the spec doesn't own; the entry point itself must be real. 5. **Match the project's existing test conventions** before inventing new ones — reuse its builders, fakes/mocks, and fixtures rather than writing ad hoc setup per spec. 6. **New specs are pending by default**, marked so cleanly (not failing loudly) until a `builder` task makes them pass. 7. Never invent acceptance criteria. If a story is underspecified, stop and send the user back to `user-stories` to tighten it. ## Examples and per-stack mechanics - **`references/backend-csharp.md`** — test framework detection, the shape mapped onto NUnit (or xUnit), a full worked example, file/naming convention. - **`references/frontend-lit.md`** — test framework detection, the shape mapped onto native `describe`/`it` blocks, a full worked example, file/naming convention. ## Open question: before or alongside implementation? This skill assumes specs are written and pending before `feature-build` dispatches the `builder` for the matching task — strict TDD. Writing tests alongside the implementation instead, with the same one-assertion/happy-then-sad rigor applied after the fact, is equally legitimate. Confirm which stance a project wants once, early (e.g. in its `CLAUDE.md`), rather than letting it drift task by task.