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: 326

Dependents: 7

Suggesters: 0

v0.1.1 2026-11-11 12:12 UTC

README

Early, version 0.x. Not ready for real projects yet; the minor version is the breaking one.

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 Spec tab, beside Barnark's architecture. It works without Barn too: barnspec init makes any project a barn.

The easiest way to use it is Barnspec GUI, in your browser: its story map, the map's history phase by phase, 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's Story map for a hotel's reservations: every story once, as it reads now, under the role that wants it, with columns following a stay from establishing to terminating.

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, run init if it does not yet have a .barn/ folder:

vendor/bin/barnspec init
vendor/bin/barnspec create-story --area-of-business="Commerce" --area-of-business-meaning="Buying and selling online" \
    --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 set-example  # give a parameter an example, at any time
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

Barnspec keeps everything in the project's barn: a project whose root holds a .barn/ folder. Its records are under .barn/barnspec/: each Area of Business is a Barntree data document in areas-of-business/, beside scenarios/, work/ and refinements/. Commit the barn with your code. Barnspec finds the barn from any folder inside it, and writes nothing anywhere else.

With no barn, Barnspec refuses to read or write. A tool built on Barnspec opens it with new BarnspecApiFactory()->open($folder, $fileStore), or BarnspecReadOnlyApiFactory to only read; both throw NoBarnFoundException, naming the folder, when there is no barn. To begin a spec, call start($folder, $fileStore), which makes .barn/ in that folder if it has none. Inside another barn it refuses with InsideAnotherBarn unless you pass insideAnotherBarn: true.

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 history --output-dir=docs/history --stories-dir='../stories/{area-of-business}'   # HTML history, phase by phase
vendor/bin/barnspec map --area-of-business=commerce                      # the story map, printed: every story once, as it reads now

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/barnspec work:delete commerce <ticket-id>                # scrap a ticket opened by mistake
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, otherwise green once it has passed a scenario-bridge run and red until then, or after a run fails. A Scenario with no ticket and no run has no colour. 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.

Tickets are disposable. Releasing a Phase deletes the done tickets in its area of business, except those of a Scenario not run since, which they keep red. work:delete deletes one at any time. The runs stay, so deleting a done ticket changes no colour. Deleting an open one leaves the colour to the runs, and opening it had already discarded the last one, so run the Scenario again. Deleting a Scenario or a Story deletes its tickets and runs with it.

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 .barn/barnspec/settings.json.

Related packages

More docs

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

License

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

Unfinished authoring

SaveRefinement stores a labelled JSON authoring snapshot for an area of business without creating formal stories, scenarios or proof. GetRefinements retrieves those snapshots through either public API factory. Refinements are separate records under the configured Barnspec root; keep them with the project data when backing up. They do not change the scenario or release lifecycle.