jonnifyagile agents
jonnify / Agile Agent Workflow / A2 · Decomposition / A2.05 / A2.05.3 · Vertical, not horizontal

A2.05 · Splitting · dive 3

Cut down, not across

A split has a direction, and only one direction yields stories. Cut down through the layers and every slice can be shown; cut across them and every slice is a fragment.

A vertical slice threads the Portal’s store, domain, and surface for one story, so a role can use it the day it lands. A horizontal slice takes one layer at a time — the database, then the API, then the page — so no role can use anything until the last layer lands. Toggle the cut on the right to see the same story divided both ways and count how many slices are demoable end to end.

Cut the same story both ways · toggle the direction

surface domain store browse enrol open track vertical: each slice threads all three layers · every one demoable
cut vertically → 4 slices, 4 demoable end to end. Each threads all 3 layers for one story, so a role can use every one.

The same work, two directions

The Portal stacks three layers: a store (data and ids), a domain core (the framework-free rules), and a surface (the web app, the bot, the dashboard). A split runs through that stack one of two ways. A vertical cut takes one thin thread through all three layers for a single story — enough store, enough domain, enough surface to let a role do one new thing. It is demoable end to end, because the thread reaches all the way through.

A horizontal cut takes one whole layer at a time — the courses table, then the courses API, then the courses page. Each layer is real, and each can be small. But none is demoable on its own: the table serves no learner, the API serves no learner, and only when the page lands does anyone see anything. The output of a horizontal cut is a fragment — a slice only another slice can use. Same destination, same total work; the difference is whether each slice ships value the day it lands or waits on the layer above it.

vertical slice
One thin thread through store, domain, and surface for one story. Demoable, because it is end to end (the A2.01.3 shape).
horizontal slice
One whole layer across the system — all the tables, or the whole API, or the entire page. Real, often small, and not demoable alone.
fragment
The output of a horizontal cut: a slice only another slice can use. It passes Small but fails Valuable — it shows a role nothing.
demoable end to end
The property a split must preserve: each slice can be shown to some role on its own. The test that tells a value slice from a layer.

This is the direction A2.01.3 drew for one story; here it is the rule for a split — every seam in the previous dive cuts vertically for exactly this reason.

Which role can demo each slice

The hero counts the demoable slices; this view names the reason — a slice is demoable only if some role can be shown it. Step across the slices of both cuts. Each vertical slice names the role it serves: a learner can browse, enrol, open a lesson, track progress. Each horizontal slice names no role yet: the courses table, the courses API, and the courses page each serve a learner nothing until the thread reaches the surface.

That is the whole test, made concrete. A slice a role could be shown is a story; a slice only another slice can use is a layer. Reading the role off each slice is how an Operator tells a value split from a layered one before handing the rung to the Author — and it is why the four patterns all cut down, never across.

Read the role each slice serves · switch the slice

slice browse the catalogue VERTICAL a learner can demo it verdict a whole capability
browse the catalogue (vertical) → a learner can demo it. A whole capability that ships the day it lands.

Read the role off each slice: a slice a role can be shown is a story; a slice only another slice can use is a layer.

The cut on the Portal

On the Portal — the learning platform this course builds — “manage the catalogue” cut the right way is the value ladder: browse → enrol → open a lesson → track progress. Each rung threads all three layers for one story, so each is demoable the day it lands. Cut the wrong way, the same work becomes the courses table → the courses API → the courses page: three slices, each one layer, none demoable on its own. The table serves no learner, the API serves no learner, and only the page shows anything — and only after the two below it land.

The ids the slices rest on are already minted — Portal.ID.generate/1 hands back a typed id and Portal.ID.decode/1 reads its .type back — so no slice waits on another to define identifiers. What makes a horizontal slice wait is the layer boundary, not the data. The companion Functional Programming course teaches the Portal’s internals; this course decides the direction of the cut.

# "manage the catalogue" — same destination, two directions.

# VERTICAL → each slice threads store + domain + surface → demoable the day it lands:
#   browse → enrol → open a lesson → track progress        (4 / 4 demoable)

# HORIZONTAL → each slice is one whole layer → a fragment until the surface lands:
#   courses table → courses API → courses page             (0 / 3 demoable)

id = Portal.ID.generate(:course)        # ids are minted — the layer boundary is what makes a slice wait, not the data
assert Portal.ID.decode(id).type == :course

The principle

A split must stay vertical — every slice demoable end to end. Splitting by horizontal layer (database, API, UI) yields fragments no role can use until the last one lands.

On the Portal

“Manage the catalogue” cut vertically is browse → enrol → open → track, each demoable; cut horizontally it is table → API → page, three fragments.

Cut down through the layers and every slice is a whole capability; cut across them and every slice is a fragment that waits on the one above it.

Recap — a split has a direction

Vertical cuts thread all the Portal’s layers for one story, so each slice is a whole capability a role can demo the day it lands; horizontal cuts take one layer at a time and leave fragments no role can use until the last one lands. The test is demoable-end-to-end: a slice a role could be shown is a story; a slice only another slice can use is a layer. That closes A2.05 — the signal to split is an INVEST failure, the patterns name the seam, and the cut must always run vertically. With stories that are valuable, well-formed, invested, and well-sliced, the chapter turns to pinning each one down with concrete acceptance.

Next in A2 — the chapter turns ready, well-sliced stories into acceptance criteria: concrete Given/When/Then examples that say exactly when a rung is done. Return to the A2.05 module hub or the A2 chapter navigation to continue.

References

The sources behind the vertical-slice direction, and where it connects in the course.

Sources

Related in this course