A2.07 · Workshop · dive 1
Vision to stories
A unit of value is a change in what a role can do. The F6 web vision is one line; it reads into nine real stories, each owned by a real role.
The Portal’s web surface — chapter F6 in the companion course
— began as one sentence: serve the Portal to people. That vision decomposes into
nine rungs (f6.1–f6.9), and each
rung is a real user story owned by a real role: an operator who can run the platform, a
learner who sees errors inline, a developer who gets a build error on a
bad link, a visitor, an architect. Every story below is quoted
verbatim from the actual f6.N.stories.md. Drag the slider on the right to read
the vision into one rung’s real story.
Read the F6 vision into one rung’s real story · drag the slider
One vision, nine real stories
The Portal’s web surface was specified, built, and proven as chapter F6 in the
companion course. Its vision is one line: serve the Portal to people. A vision names a
destination, not a slice — so to turn it into work, read it into a ladder by asking, for every rung,
which role gains what capability. The answer is the rung’s user story. F6 has nine
rungs, and each one is a real As a <role>, I want… so that…
line, quoted here verbatim from its f6.N.stories.md.
The roles are not generic. The first rung belongs to an operator — F6.1-US1: “As
an operator, I want the Portal to boot as a Phoenix application, so that I can run and serve it with the
standard Elixir/Phoenix toolchain.” The form errors belong to a learner —
F6.5-US5: “As a learner, I want validation errors shown on the form, so that I can fix a bad submission
without losing context.” The live search belongs to a learner too — F6.6-US1: “As a
learner, I want the course list to filter as I type, so that I find a course without submitting or
reloading.” A developer owns the safety rungs — F6.2-US4: “As a developer,
I want every internal URL verified at compile time, so that a renamed or mistyped route is a build error, not
a broken link in production.” Each rung calls only the unchanged Portal facade;
F6.6’s live search is built at /elixir/phoenix/liveview.
- F6.1
- operator — boot as a Phoenix application, run it with the standard toolchain.
- F6.2
- developer — every internal URL verified at compile time, not a broken link in production.
- F6.3
- operator — catalog and event data in PostgreSQL, nothing lost across a restart or deploy.
- F6.4
- developer — contexts call each other only through public functions; the graph stays acyclic.
- F6.5
- learner — validation errors shown on the form, fix a bad submission without losing context.
- F6.6
- learner — the course list filters as I type, find a course without submitting or reloading.
- F6.7
- learner — the catalog updates when someone else changes it, fresh without reloading.
- F6.8
- learner — create an account and sign in, a real identity on the platform.
- F6.9
- operator — counts that seed once then update live, read activity without re-querying.
Two more real roles appear off the spine: a visitor (F6.1-US2 — “open a course page for a given user”) and an architect (F6.5-US0 — “each URL named after the resource it returns”). Naming the role on every rung is how a vision becomes value rather than a pile of tables and routes. The whole F6 chapter is built under /elixir/phoenix.
Value, not tasks — the test
A vision implies chores — “add a courses table”, “wire up a Phoenix route”. Those read like work, but they are not stories: they name a database or a router change with no role and no capability. The test for a unit of value is one question — does the line name a change a role can do? A line that does has a role and a verb that role can act on; it is a story. A line that does not is a task: restate it as the value it serves before it earns a place on the backlog.
Switch the candidate below. Real F6 stories are mixed with tautological task-phrasings; the classifier runs the one test and reports the verdict, naming the role and the change for a story, or the missing role for a task.
Does the line name a change a role can do? · switch the candidate
A story names a role and a change that role can use; a task names a chore — restate the task as its value, or leave it off the backlog.
The nine stories, written out
On the Portal — the learning platform this course builds — reading the vision into roles yields
these nine stories. Each is the real Connextra line from its f6.N.stories.md, quoted
verbatim; none is paraphrased. Read top to bottom and the vision “serve the Portal to people”
resolves into a sequence of named roles, each gaining one capability. The Portal’s internals —
the branded store and the event-sourced engine behind one facade — are built in the
companion F6 chapter; here the work is the stories, not the code.
# Vision: serve the Portal to people. # Read it into nine rungs — one role, one capability each (verbatim from f6.N.stories.md). F6.1 # operator As an operator, I want the Portal to boot as a Phoenix application, so that I can run and serve it with the standard Elixir/Phoenix toolchain. F6.2 # developer As a developer, I want every internal URL verified at compile time, so that a renamed or mistyped route is a build error, not a broken link in production. F6.3 # operator As an operator, I want catalog and event data stored in PostgreSQL, so that nothing is lost when a node restarts or a new release is deployed. F6.4 # developer As a developer, I want contexts to call each other only through public functions, so that boundaries hold and the dependency graph stays acyclic. F6.5 # learner As a learner, I want validation errors shown on the form, so that I can fix a bad submission without losing context. F6.6 # learner — built at /elixir/phoenix/liveview As a learner, I want the course list to filter as I type, so that I find a course without submitting or reloading. F6.7 # learner As a learner, I want the catalog to update when someone else changes it, so that what I see stays fresh without reloading. F6.8 # learner As a learner, I want to create an account and sign in, so that I have a real identity on the platform. F6.9 # operator As an operator, I want course and enrollment counts that seed once and then update live, so that I read platform activity as it happens without ever re-querying.
A unit of value is a change in what a role can do. Name the capability a role gains — never the table, route, or schema the change happens to need.
The F6 vision “serve the Portal to people” reads into nine rungs, each a real user story owned by a real role — F6.6-US1, a learner who filters the catalog as they type.
A vision becomes a backlog when every rung names a role and a change that role can use — quoted from the spec, not invented.
Recap — one vision, a ladder of role-stories
The F6 vision — serve the Portal to people — read into nine real stories, one per rung, each owned by a named role: an operator who boots and runs the platform, a developer who gets compile-time link safety, a learner who sees errors inline and searches as they type. The test that separated value from a task was a single question — does the line name a change a role can do? A story has a role and a capability; a task names a chore. The ladder is a backlog, but not yet a refined one: some rungs are still too big to build in one slice. The next dive takes one rung and splits it, re-testing each piece.
Next in A2.07: A2.07.2 · Split and test — take one rung (F6.6
LiveView), show it as its four real artifacts, and prove it by the Given/When/Then in its
f6.6.stories.md.
References
Primary sources for reading a vision into role-owned stories, and the real F6 chapter this dive quotes.
Sources
- Cohn, M. — User Stories Applied — writing stories as value, in the role-want-reason form.
- Adzic, G. — Specification by Example — concrete examples as the shared definition of done.
- Humble & Farley — Continuous Delivery — small, demoable units as the basis of a deliverable backlog.
Related in this course
- Companion · F6 Phoenix chapter — where the nine rungs are specified, built, and proven.
- /elixir/phoenix/liveview — F6.6, where the learner’s live search (F6.6-US1) is built.
- A2.07 · Workshop: decomposing Portal — the module hub.
- A2.07.2 · Split and test — the next dive.
- A2.01 · Value, not tasks — the first move.
- A2.02 · The Connextra form — the story form.
- A2.03 · INVEST — the readiness gate.
- Companion · Functional Programming in Elixir — the Portal’s internals.