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

Package info

bitbucket.org/rmb32/barnspec/

Homepage

pkg:composer/rmb32/barnspec

Statistics

Installs: 193

Dependents: 7

Suggesters: 0

v3.0.1 2026-10-30 09:21 UTC

This package is auto-updated.

Last update: 2026-10-30 09:26:24 UTC


README

Part of Barn.

Capture user stories and their Given/When/Then acceptance scenarios in plain language, in one place, and turn them into readable documents, a glossary, a visual story map, tracked work tickets and runnable tests.

You describe stories and scenarios once, one question at a time in the GUI, in the same "Complete the sentence…" style throughout — no code or framework knowledge needed. Until its Phase is released, anything can be reworded or deleted. Everything is written back as sentences that still read correctly, so anyone on the team can review it.

In a barn it is the Business tab, beside Barnark's architecture. It works on its own in any project too.

The easiest way to use it is Barnspec GUI, in your browser: the story map, every capture flow and the Work board. The command line does the same from a terminal, and is the better fit for scripts, CI and AI agents.

The Barnspec GUI story map for a hotel's reservations: columns follow a guest's journey, rows are Phases of work, and each story card shows its real state.

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 rmb32/barnspec-gui
vendor/bin/barnspec gui        # opens the GUI in your browser

rmb32/barnspec is the library; barnspec-cli provides the vendor/bin/barnspec binary, and barnspec-gui adds its gui command. Leave the GUI out where only the command line is needed. See the quick start for shorter ways to type it.

Quick start

From your project's root:

vendor/bin/barnspec create-story --area-of-business="Commerce" --role="Customer" --role-meaning="Someone who buys" \
    --goal="update basket quantities" --reward="get exactly what they want"
vendor/bin/barnspec refine     # add Given/When/Then Scenarios
vendor/bin/barnspec reword     # change the wording, until its Phase is released
vendor/bin/barnspec show       # see what's been captured

refine is interactive on purpose — some questions (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, restage-story, delete, create-scenario --file=…, show --json). The quick start walks through both side by side.

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 across every area of business rather than defined per area of business, so story maps across areas of business 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), until the Story's Phase is released. After that the stage is locked like the rest of the Story, and changes only through an elaboration.

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"

A Phase is released only once it is proven: every Story in it green, each of its Scenarios with its tickets done and a passing run recorded. An empty Phase has nothing proven, so it can't be released. An elaboration that only rewords, restages or retires needs no run. 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

Outside a barn, Barnspec stores readable, diffable JSON under .barnspec/ at your project root — one document per Area of Business and one for its Scenarios. Commit it with your code.

In a barn (a project whose root holds .barn/barn.json), Barnspec keeps its own records under .barn/barnspec/ and manages the Area of Business structure through Barncept under .barn/concepts/. The Barnspec GUI and CLI still use the Barnspec API. On first use in an existing barn, Barnspec safely migrates legacy Area of Business JSON from .barn/barnspec/areas-of-business/, verifies the copy, and retains the original files. A conflict stops migration before any records are written. Barnspec records the selected store in .barn/barnspec/area-of-business-storage.json; subsequent commands and the Barn status view follow that selection. Every Barnspec command finds the barn from any folder inside it.

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/ (in a barn, .barn/barnspec.json).

Related packages

More docs

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

License

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