Search by

rmb32 / barnspec

rogerbarnfather

Capture user stories and Given/When/Then acceptance scenarios as a living Specification — story mapping for a Business Driven approach

v1.0.0 2026-10-07 12:58 UTC

This package is auto-updated.

Last update: 2026-10-07 18:34:09 UTC


README

Part of BarnSuite.

Given When Then — capture user stories and acceptance scenarios in plain language, in one place (Specification), and turn them into readable documents, a glossary, a visual story map, tracked work tickets and runnable tests.

You describe stories and scenarios once, through an interactive wizard, in the same "Complete the sentence…" style throughout — no code or framework knowledge needed. Everything is written back as sentences that still read correctly, so anyone on the team can review it.

Requirements

  • PHP 8.5+
  • Composer

The ds PHP extension is used when present but isn't required: the php-ds/php-ds polyfill comes in as a dependency and satisfies it.

Installation

composer require --dev rmb32/barnspec rmb32/barnspec-cli
vendor/bin/barnspec list

rmb32/barnspec is the library; barnspec-cli provides the vendor/bin/barnspec binary. See the quick start for shorter ways to type it.

Quick start

From your project's root:

vendor/bin/barnspec draft      # capture a rough story
vendor/bin/barnspec review     # reword it into a real Story
vendor/bin/barnspec refine     # add Given/When/Then Scenarios
vendor/bin/barnspec show       # see what's been captured

draft, review and refine are interactive on purpose — some questions (does this wording ring true? accepted or rejected?) are a human judgement call. Everything else has a non-interactive form for scripts, CI and AI agents (create-area-of-business, create-phase, create-story, restage-story, create-scenario --file=…, show --json). The quick start walks through both side by side, with example screens.

The lifecycle backbone

A Story can sit at one stage of the role's life with the business — establish, adjust, transact, resolve or close, in that order. The vocabulary is fixed for the whole suite rather than defined per area, so story maps across areas line up column for column. It is deliberately not CRUD: transact and resolve have no mutation-verb analogue, which is the point — the ordering principle is where in the lifespan a story sits, not which verb it uses.

A stage is optional. A Story without one is Unassigned — a permanent home for the stories that genuinely are not about a lifespan (reporting, compliance, notification), not a staging area. Set one at capture time (create-story --stage=…, or the skippable step in review) or afterwards (restage-story, or the selector on a card in the GUI).

Changing a released Story

Once a Story's Phase is released its Scenarios no longer change directly — create-scenario and the editor refuse, and say what to run instead. A change goes through an elaboration of the Story in the active Phase:

vendor/bin/barnspec elaborate-story --area-of-business=commerce --story=add-a-product-to-the-basket \
    --goal="add any product to the basket"          # optional new wording
vendor/bin/barnspec create-scenario --file=new-case.json      # with "elaboration": true
vendor/bin/barnspec create-scenario --file=better-case.json   # with "amends": "<scenario slug>"
vendor/bin/barnspec retire-scenario --area-of-business=commerce --story=add-a-product-to-the-basket \
    --scenario=adds-a-unit-to-a-locked-basket
vendor/bin/barnspec withdraw-from-elaboration …              # undo a pending change

refine offers a released Story once it is elaborated, and captures into the elaboration. When the Phase is released the elaboration is merged into the Story: its new and amended Scenarios hold from then on, retired ones stop holding, and what was replaced is kept as history. Until then scenario-bridge run-all --released skips the Scenarios being changed, so the released Phases stay green while the new behaviour is built.

Was the reward delivered?

Scenarios prove a Story's goal. Its Impact records whether the reward followed. Each Story gets one per Phase it shipped in, as dated, attributed observations: evaluating, achieved, none or superseded.

vendor/bin/barnspec release-phase --area-of-business=commerce   # asks about earlier Phases' rewards first
vendor/bin/barnspec record-impact --area-of-business=commerce --story=add-a-product-to-the-basket \
    --state=achieved --observation="I filled my basket in one visit" --source=role --who="a regular customer"

release-phase never refuses to release because a reward is unanswered; it asks, and you can leave any answer blank. achieved is settled only by the role or someone speaking for them. Impact never changes a Story's colour.

Where your data lives

Everything is written as readable, diffable JSON under .barnspec/ at your project root — one document per area of business (.barnspec/areas-of-business/<slug>.json) and one for its scenarios (.barnspec/scenarios/<slug>.json). Commit it with your code.

vendor/bin/wizard-reset (from Barnspec CLI) previews wiping it all so you can start over; add --force to do it.

Render what you've captured

vendor/bin/barnspec write commerce --output-dir=docs/stories/commerce  # one doc per Story
vendor/bin/barnspec glossary commerce --output=docs/glossary.md          # ubiquitous-language glossary
vendor/bin/barnspec glossary --output-dir=docs/glossary                  # every area, plus a linked index.md
vendor/bin/barnspec map --output-dir=docs/map --stories-dir='../stories/{area-of-business}'   # HTML story map

The same three are available as vendor/bin/barnspec write | glossary | map.

Link scenarios to real work (Work)

Work tracks tickets against Scenarios and is the source of truth for their status. Every work:* command names the area, the Story and then the Scenario within it.

vendor/bin/barnspec work:create commerce basket-quantity-updates caps-at-the-stock-level --title="Cap quantity" --reference=SHOP-42
vendor/bin/barnspec work:list commerce basket-quantity-updates caps-at-the-stock-level
vendor/bin/barnspec work:status commerce <ticket-id> in-progress    # to-do | in-progress | done
vendor/bin/scenario-bridge run commerce caps-at-the-stock-level    # this is what turns it green

A Scenario's fulfilment colour is worked out live: yellow while any ticket isn't done, red when all are done but the Scenario has not passed a scenario-bridge run, green once it has. There is no command to confirm a Scenario by hand — a passing run is the only thing that makes one green, and a later failing run takes it back to red. work:list prints the last run beside the colour, so a red Scenario says whether it has never been run or is currently failing.

A recorded run never expires on a clock. Creating a new ticket on a green Scenario drops it back to yellow and discards the run: the evidence predates the new work, so the Scenario has to be run again once that ticket is done.

A Story's colour is then rolled up from its Scenarios rather than stored: green when every Scenario is green, red when every Scenario is red or green and at least one is red, yellow otherwise — including while one Scenario is untouched and a sibling is already under way. A Story with no Scenario at all has no colour, and work:create refuses it: run refine and capture one concrete case first.

Turn scenarios into running tests

Two optional packages take your captured Scenarios to executable tests:

vendor/bin/port-generator generate commerce            # write Arrange/Assert/Act/Authenticate stubs
# fill in the stubs with real application logic, then:
vendor/bin/scenario-bridge run commerce basket-quantity-updates
vendor/bin/scenario-bridge run-all commerce --summary --xml-report=build/report.xml

See Port Generator and Scenario Bridge. Configure where stubs go in a barnspec.json next to .barnspec/.

Browser UI

Barnspec GUI offers the same capture flows and a Work board in the browser:

BARNSPEC_ROOT=$PWD/.barnspec php -S localhost:8080 -t path/to/barnspec-gui/public

Related packages

More docs

Quick start · Philosophy · Contributing · Internals · History · Known issues

License

Proprietary. See LICENSE. Copyright (c) Roger Barnfather.