A scaffold for spec-driven development that uses a behavior-driven approach to keep code aligned with the intent articulated in specs: business use cases are written as Gherkin scenarios inside Markdown specs, and those scenarios run as the acceptance suite that every change must keep green.
- Intent articulated in the spec. The behavior-driven approach lets us express the intent behind an implementation in the specification itself, as business use cases; the acceptance suite continuously checks that the code honors them.
- Spec as source. This repo establishes the foundational aspects of spec-as-source development: directly updating code without first updating the spec is forbidden. Every change starts as a spec delta whose red scenarios define the work.
- Keeping agents on the articulated use cases. An experiment in preventing a coding agent from deviating from the business use cases we have articulated — enforced mechanically (hooks, an always-green acceptance suite), not by prompt discipline alone.
- Acceptance tests must always pass. Run the suite after every code change; never leave it red. If failing code was written without a driving spec delta, it is reverted and redone spec-first — never patched into passing.
- Specs and code are never modified together. Enforced live by a zone-guard hook (
tasks.mdfiles exempt).
Specs here are managed with OpenSpec and the behavior-driven schema, but OpenSpec is only one example — the same approach works with other spec-driven tools such as Spec Kit.
This is the openspec/config.yaml used in the video above:
schema: behavior-driven
context: |
PollCast is an intuitive web application allowing users to instantly create,
share, and track custom polls. To prevent spam without the friction of
passwords, the platform features a streamlined UI where participants simply
cast votes using their email address as a unique identifier, guaranteeing
highly accurate and duplicate-free poll results.
Tech stack: Node.js, server-side rendered Express, JSON file store to begin with.
rules:
proposal:
- Less than 200 words
specs:
- >-
Specs are Markdown: specs/<capability>/spec.md, with prose anywhere and
all executable Gherkin inside column-0 ```gherkin fences. Extraction is
line-preserving, so reported lint/test line numbers map 1:1 to the
spec.md.
- |-
Before considering a spec complete, extract the Gherkin and lint it with
the gherkin-lint npm module, fixing all reported issues:
node .claude/skills/acceptance-test-authoring/references/extract-gherkin.cjs openspec acceptance-tests/.extracted \
&& npx --yes gherkin-lint --config .claude/skills/acceptance-test-authoring/references/gherkin-lintrc.json acceptance-tests/.extracted
(or `npm --prefix acceptance-tests run lint:specs` once the runner
project exists). Pass acceptance-tests/.extracted as a DIRECTORY
argument, never a quoted glob — globs silently match nothing through the
dot-directory — and always pass --config: gherkin-lint has no default
rules. The extraction output is gitignored and written via Bash, which
the spec/code zone guard does not intercept (it guards file edits only)
— running this in a specs-zone session is legal by design; do not "fix"
it. Use ctx7 for documentation on gherkin-lint.
tasks:
- Use ctx7 for any documentation on npm modules