jonnifyagile agents

A5.4.3 · dive 3/3

Acceptance gates

The Directive sets the agent in motion; the gate is where it stops. An Acceptance gate is the runnable check that closes a story — and the line between “the agent thinks it is done” and “the work is provably done.”

A gate is not the agent's self-report. It is a single command whose pass or fail is unambiguous: a clean compile, a real render, a static grep, a self-heal. Every well-formed agent story carries exactly one; a story with no gate can never close, because the agent has work to do but no signal it is finished. Select each story on the right to read the runnable check that closes it, drawn verbatim from the Portal's real f6.1.llms.md.

Each story's closing check · select a story

F6.1-AS1..AS4 · each story closes on a gate AS1 · boot as a Phoenix app gate: boot AS2 · render a user's courses gate: render AS3 · hold the boundary gate: grep AS4 · self-heal and fail soft gate: restart + 422 acceptance gate — the runnable check that closes the story mix compile clean; app boots; GET /health 200; tree order store → engine → endpoint
F6.1-AS1 (boot as a Phoenix app) closes on a boot check: mix compile clean, the app boots, GET /health returns 200, and the tree order is store → engine → endpoint. The gate is one runnable check, not a self-report.

What a gate is

An agent story has two halves: a Directive (what the agent does) and an Acceptance gate (the check that closes it). The previous dive paired them; this one isolates the gate. A gate is a single runnable check whose pass or fail is unambiguous — a command the Operator (or a script) runs, not a sentence the agent writes about its own work. “Done — it compiles” is a self-report. GET /health returns 200 is a gate.

The distinction matters because an agent's report and the truth can diverge. A gate removes the gap: it makes “done” a closure over a check the human ran, not an opinion the agent stated. A story with no gate is a Directive with no closing condition — the agent has work to do, but nothing tells it, or the reviewer, when the work is finished.

A self-report

The agent states it is finished. The claim and the reality can diverge, and nothing the human can run resolves the difference.

A gate

A single runnable check whose result is unambiguous. The Operator runs it; the story closes on its pass, not on the agent's word.

The four gates

The Portal's web bootstrap, f6.1.llms.md, carries four agent stories, and each one closes on a different kind of runnable check. F6.1-AS1 closes on a boot — a clean compile, a running app, GET /health returning 200, and the tree booting store → engine → endpoint. F6.1-AS2 closes on a real render — a known user renders their courses, no enrollments renders an empty state, and the template references only assigns. F6.1-AS3 closes on a static grep: grep -rE "Portal\.Engine|Repo|GenServer\.call" apps/portal_web/lib/ must return nothing — the boundary that keeps the web layer calling only the facade, never the engine. F6.1-AS4 closes on a self-heal and a fail-soft — killing the endpoint restarts it and a later request succeeds, and an injected %Portal.Error{} renders 422, never 500.

# f6.1.llms.md — the Acceptance gate of each agent story (verbatim checks)
#
F6.1-AS1  # boot    mix compile clean; app boots; GET /health 200; tree order store → engine → endpoint
F6.1-AS2  # render  a known user renders their courses; no enrollments renders an empty state; template references only assigns
F6.1-AS3  # grep    grep -rE "Portal.Engine|Repo|GenServer.call" apps/portal_web/lib/ returns nothing
F6.1-AS4  # heal    killing the endpoint restarts it; an injected %Portal.Error{} renders 422, never 500

Four stories, four kinds of check, but one property in common: every gate is a command, and its result is yes or no. The hero figure above lets you read each gate against its story; the figure below shows what happens to a story that has no gate at all.

Each story closes on a runnable check, not a claim — a boot, a render, a grep, or a self-heal, each with an unambiguous result.

A story with no gate

All four of f6.1.llms.md's stories carry a gate, so the count of stories that can never close is zero. Add a story with a Directive but no Acceptance gate and the picture changes: the agent has work to do, but no check exists to close it. The story is incomplete by construction — not because the work is hard, but because nothing defines when it is finished.

Toggle the figure between the four real stories and the same set with a gateless story added. The readout counts the stories that cannot close. A brief that ships a story without a gate ships work with no end — the agent runs, the reviewer waits, and “done” never becomes provable.

Stories that can never close · add a gateless story

a story closes only if it has a gate AS1 · boot as a Phoenix app gated AS2 · render a user's courses gated AS3 · hold the boundary gated AS4 · self-heal and fail soft gated AS5* · a story with a Directive but no gate no gate stories that can never close: 0 missing
All four agent stories have a gate: 0 missing. Each one closes on a runnable check — a boot, a render, a grep, a self-heal — so every story can be proven done.

A gate is the line between “the agent thinks it is done” and “the work is provably done” — a story without one can never cross it.

On the Portal

The two gates that carry the most weight in f6.1.llms.md are the ones that protect the architecture, not the feature. F6.1-AS3 closes on the master-invariant grep — no module under apps/portal_web/lib/ may name Portal.Engine, Repo, or GenServer.call — so the web layer is held to calling only the Portal facade, never reaching past it. F6.1-AS4 closes on the endpoint self-healing: kill PortalWeb.Endpoint and the :one_for_one supervisor restarts it, and an injected %Portal.Error{} renders 422, never a 500. Both gates are checks a human runs and reads, not claims the agent makes.

The principle

The Acceptance gate is the runnable check that closes a story; a story with no gate is incomplete, because nothing defines when its work is done.

On the Portal

f6.1.llms.md closes F6.1-AS3 on grep … apps/portal_web/lib/ being empty and F6.1-AS4 on the endpoint self-healing under :one_for_one with an injected %Portal.Error{} rendering 422.

A gate is the line between “the agent thinks it is done” and “the work is provably done.”

Recap — the gate closes the story

An Acceptance gate is the single runnable check that closes an agent story: a boot, a render, a grep, a self-heal — each a command whose pass or fail is unambiguous, run by the human, not reported by the agent. Every story in f6.1.llms.md carries one; a story with no gate can never close. That completes A5.4: a user story says what someone needs, and an agent story says what the agent does (the Directive) and how the work proves itself done (the gate). The next module assembles the four parts — references, requirements, topology, and stories — into the single implementation prompt the agent runs.

Back to the hub: A5.4 · Agent stories — the Directive and the gate, the first two stories, and the gate that closes each one.

References

Primary sources on what makes a story closeable — a testable acceptance criterion rather than an open goal — and where the stories these gates close, and the boundary one of them guards, are defined in the courses.

Sources

Related in this course