Stories and acceptance criteria
A story is a small, verifiable piece of work with acceptance criteria and a Demonstrate block that shows the outcome.
A story is the piece of work kanman takes on: one issue in your tracker, small enough for one pull request, with acceptance criteria that say exactly when it is done. kanman only picks up stories that are ready, and it proves each finished story against its criteria before anyone reviews the code.
Where stories come from
Stories come from two places:
- Your tracker. An issue in the connected project becomes a story on the team page once it is marked for kanman: it carries the pickup label (
kanmanby default) or is assigned to the account set in the team’s tracker settings. Unmarked issues never appear on the team page. - Intake. Describe a requirement to kanman in the conversation (press
Nto start with the team you are looking at), or ask kanman in Slack or Microsoft Teams (see Work with kanman in Slack and Microsoft Teams). kanman drafts stories and shows them as a card for you to approve or reject; Open review opens a page to edit them first. Approved stories are written to your tracker in one batch, with the pickup label. A story gets its key (for exampleSBX-12) when you approve it, so rejected drafts leave no gaps in the numbering.
Triage comes first
Every message kanman receives on intake is classified as exactly one of four kinds:
| Kind | What happens |
|---|---|
| Reply to an open decision | The answer is applied to that decision |
| Status question | kanman answers in the conversation. The answer is never committed to the repository |
| Operational request: pause or resume the team (admins only), cancel a run, expedite or deprioritise a story | kanman carries it out and confirms |
| Work request | kanman drafts stories |
Only work requests become stories, so a question like “what is blocking SBX-12?” never turns into a ticket. If a request is too vague, kanman asks up to three questions first; answer them on the request page and kanman drafts again.
Why a story exists
Every story starts with Why this exists, right under its key. In one short paragraph kanman says where the story came from and who said yes to it, for example:
From your message on 2 Oct: “The section switcher is cluttered and barely usable. Please optimize it.” I drafted it as “Allow pinning favorite sections to the top”, then split it in two. Nobody has said yes to it yet, so I won’t build it until someone does.
Below the paragraph, each place the story came through is a link: your request (the quoted words open the message you wrote, Your request opens its review page), the story it was split from or follows up, the outcome it belongs to, or the issue in your tracker. A story can come from:
| Origin | Example |
|---|---|
| Your request | A message to kanman in the app, Slack or Microsoft Teams, a mention, or a request from Claude Code, which kanman drafted into the story |
| Your tracker | An issue someone wrote in the connected tracker |
| Something kanman can check | A failing pipeline, a security finding, a dependency update or an incident |
| You | A story you wrote yourself |
| kanman | Something kanman proposed itself, for example an item it left for later when it delivered another story, with its reason |
| A split or a follow-up | A part of a larger story, or work that follows another story |
| An outcome plan | A story kanman filed for an outcome’s plan |
The paragraph ends with the yes: who approved the story and when, that kanman approved it itself under the team’s autonomy, or that nobody has said yes yet. The story’s history at the bottom of the page still lists every change.
kanman never adds scope on its own
kanman only builds what a person asked for. A story whose scope nobody confirmed never moves to Ready or starts, whatever the team’s autonomy:
- a request kanman turned into a feature in its own words, until you approve the draft;
- something kanman proposed itself, such as a follow-up;
- a part of such a story after a split;
- a story an outcome’s plan added, unless a person approved that plan.
These stories show Waits for a yes on the board. kanman asks the person who made the request (or the team’s responsible person) once per request: “May I build it as I drafted it?” with Yes, build it as written, Edit it first and Drop it. On autonomous teams the question joins your other questions in one bundle. You can also say yes on the story itself, or move it to Ready yourself: that move is your yes too. Drop it closes the story as won’t do; nothing is deleted.
Drafts that fit your team
kanman drafts for the team you actually have. Before a draft reaches you, kanman checks it against the tools your team uses (its code host, where it tracks work, its chat) and against what kanman already does for the team, such as the maintenance scan or watching your pipelines. A draft that names a tool your team does not use (“file GitHub issues” for a team on GitLab that tracks its work on its kanman board) or that builds something kanman already does (a dependency audit, a lockfile check, a link checker) is drafted once more. If it still does not fit, kanman files nothing and asks you one question instead, for example “My maintenance scan already looks for this. Should I run it instead? Say ‘run the scan’.” If you do want such a tool built, say so in your request (“add a lockfile check to our pipeline”), and kanman drafts it. The same check applies to the stories an outcome’s plan proposes: a step that names a tool your team does not use is left out of the plan.
When kanman finds drafts of an earlier request that miss the mark this way, it tells the person who asked, once per request: “I misread your request. May I drop them and run the maintenance scan instead?” with Drop them and run the scan instead, Edit it first and Yes, build it as written. Dropping closes them as won’t do (nothing is deleted) and starts the scan; what it finds arrives on the board for your review.
Work with a clear trigger keeps going without asking, within the team’s boundaries: failing pipelines, security and dependency updates, stories a person wrote, approved or moved to Ready, parts of such stories, issues from your tracker, and stories inside an outcome whose plan a person approved.
Anatomy of a story
| Part | Description |
|---|---|
| Title and context | What and why, in plain words |
| Acceptance criteria | Numbered criteria in Given / When / Then form |
| Demonstrate block | A concrete, runnable way to show the outcome. Required |
| Test plan | Which tests the change needs, for example “unit: CSV serializer”, “e2e: download flow” |
| Size | S, M or L. L stories should be split before they are written |
| Affected areas | Paths or modules the change will touch, for example src/invoices/** |
| Assumptions | Details kanman settled on its own, stated in one sentence each, for example “The tab header owns the divider: 1px, border token.” Shown as What I assumed |
| Open questions | What only a person can answer: scope, product intent or a trade-off. Each question is marked Blocks approval or Doesn’t block |
| Class of service | standard, expedite, fixed_date or maintenance |
Acceptance criteria
Each criterion is written as Given / When / Then and has a stable id (ac-1, ac-2, …) that is never reused within the story:
ac-1 Given a customer with 3 invoices in March
When they export March as CSV
Then the file has 3 rows and the columns date,number,amount
During verification every criterion gets a status: pending, passed, failed or unknown. A passed criterion carries evidence: the file and line that implement it. You see this table in the evidence pack.
Changing criteria while a run waits
Once a run starts, the story is read-only: kanman builds and checks against the criteria as they were when it started. Sometimes the team learns during the run that a criterion itself was wrong, for example a page load limit of 2.5 s that cannot be met because the measurement includes your company’s single sign-on redirect.
While the run waits for you (a decision, a parked run or a failed check), owners and admins can change what a criterion says: choose Change criteria below the read-only notice on the story, or on the waiting decision on the run page. Edit the Given, When or Then of the criteria that change, say why, and save.
- The change is recorded with who made it, the old and the new wording and your reason. It appears in the run’s progress, in the evidence pack under Criteria changed during the run, and in the audit log.
- If the acceptance spec checks a criterion you changed, kanman rewrites the spec with your change, checks that it fails for the right reason, and then lets the waiting run continue on it. The waiting decision is closed for you.
- If the spec does not check it, answer the waiting decision as usual; the run continues with the new criteria.
While kanman is working on the run, the criteria stay locked and the story says so. Once the run is in review or done, start a new story for further changes.
The Demonstrate block
The Demonstrate block says how a person would see that the story works. It ends the acceptance criteria and is required for every story. It has a kind, steps and an expected outcome:
| Field | Values |
|---|---|
| Kind | ui, api, cli or config |
| Steps | What to do, in order |
| Expected | What you see when it works |
A good Demonstrate block:
Kind: ui
Steps: open /invoices, pick 2026-03-01 to 2026-03-31, click "Download CSV"
Expected: a CSV downloads with the columns date,number,amount
“Tests pass” is not a Demonstrate block. It names no outcome a person could check. A story without a Demonstrate block shows Add a Demonstrate step in the draft review and cannot be approved.
Readiness
Every story gets a readiness score from 0 to 100, built from five checks:
| Check | Passes when |
|---|---|
| Clear acceptance criteria | There is at least one criterion, and every criterion has a Given, a When and a Then |
| Testable | The story has a test plan and every criterion has an observable Then |
| Small | The size is S or M |
| No blocking questions | No open question is marked Blocks approval. While some are open, the check says how many, for example “2 questions block approval”. Questions that do not block never fail this check |
| Has Demonstrate | The Demonstrate block has steps and an expected outcome |
Each check is worth 20 points. At 100 the story shows Ready for kanman; only such stories can be approved and written to the tracker from intake.
Assumptions and open questions
kanman does not ask you what it can find out itself. Design and code details, such as which element owns a border, which color token or class to use, or where a change belongs, it settles from your repository and its conventions, and writes each choice down under What I assumed. It asks only what a person has to decide: scope, product intent, or a trade-off it cannot infer. Each question says whether it Blocks approval, and often what kanman would pick (“I would pick: …”).
Every open question has three actions, in the drafts card in the conversation, at the top of each draft in the review and on the story page:
| Action | What happens |
|---|---|
| Answer | Type a short answer and press Enter (Escape cancels). kanman works it into the acceptance criteria and the test plan, and the question disappears |
| Let kanman decide | kanman takes its own pick and records it as an assumption |
| Not relevant | The question is dropped |
Settled questions stay on the story under Settled questions, with the answer or kanman’s choice. You can also answer in the chat; see Answer kanman’s questions.
When you click Approve on a story that is not ready yet, kanman says why (“1 question blocks approval. Answer it first.”) and moves you to the first blocking question. Workspace owners and admins can choose Approve with open questions when only questions hold a story back: the questions stay on the story as notes, the approval is recorded in the audit log, and the tracker issue lists them under Open questions. The tracker issue also lists the assumptions and the answered questions, so whoever picks the story up sees what it was settled on.
The acceptance spec
If your repository has an acceptance manifest, kanman goes one step further before a story is ready. It writes an executable acceptance spec from the Demonstrate block, on a protected path in your repository (.kanman/acceptance/SBX-12/), and runs it. The story moves to Ready only when the spec runs and currently fails: a spec that already passes does not test the new behaviour. The story page shows the spec state:
| State | Meaning |
|---|---|
missing |
No spec yet. Shown as Spec: not written yet |
authored |
Written, not run yet |
red |
Runs and fails, as expected before the change. Shown as Spec: red (expected) |
green |
Passes, after the change |
invalid |
Rejected, shown as Spec: needs a fix with a reason such as “Spec passes before implementation, it does not test the new behaviour” or “Spec mocks its own target: route interception of /api/invoices” |
The details are in The outcome gate and evidence.
Splitting stories
kanman keeps stories small instead of tracking checklists inside them. When kanman drafts a large requirement, it writes several stories, each with its own criteria and Demonstrate block. A story of size L does not pass the readiness check; split it in the draft review before you approve it.
kanman also splits stories on its own as a NOTIFY action: a story of size L in Backlog or Refining with at least two acceptance criteria becomes 2 to 4 smaller stories, each with its share of the criteria. You see a one-line notice in your conversation with kanman with Undo, and the parts appear in the same column. Parts of a story nobody said yes to wait for a yes like the story itself (see kanman never adds scope on its own), and kanman never splits a draft you have not approved, a story that waits for a yes, or a draft that did not fit your team. If you want to approve splits first, raise split_story to ESCALATE in the policy; kanman then asks in the decision inbox. See What kanman does on its own.
The test plan replaces the old subtask checklist: it lists the concrete checks the change needs, and the run’s evidence pack shows which ones ran.
When kanman would rather not start
kanman does not start every story it is handed. When a story is vague, too big, risky or collides with other work, it says so before any work begins: “I’d rather not start this yet, because …”, followed by one concrete proposal instead of the work.
| Why | What kanman proposes |
|---|---|
| Another open story or run already covers most of it | Add this to that story instead |
| It touches the same files as a story that is in progress or in review (“this touches the same files as PU-41 in review”) | Wait until that story is merged |
| It has questions only you can answer | Answer them first |
| It is too big for one change (size L) | Split it, with the parts it would create |
| It is risky ground: it deletes or migrates data, or touches payments | A short spike that tries the risky part first |
You see the same words everywhere kanman talks about the story: in its reply in the conversation, in Slack and Microsoft Teams, in its answers on tracker issues and pull requests, on each draft in the drafts card and the review, and on the story page. It is a recommendation, not a lock: you decide, for example by splitting the draft or approving it as it is.
Estimates and what kanman is not sure about
Every drafted story carries an estimate: its size, an effort range and how confident kanman is, with a short reason, for example Size M · about 1–2 days · medium confidence: 3 criteria, touches the billing export. kanman never sounds surer than the facts allow: open questions, risky ground or several unknowns lower the confidence.
Under What I’m not sure about kanman lists what it could not settle, each with the reason and what would settle it: “I’m not sure which tenant the export uses because the story does not say. A look at the tenant configuration would settle it.” The same list goes into the plan kanman writes before it changes code, and the plan ends with what kanman is still unsure about.
Under Close to other work the story names the open stories, runs and pull or merge requests it overlaps with, and the files they share. Where your tracker can list its open issues, kanman compares with those too; otherwise with the stories on the board.
Before a run starts
Work moves on between drafting and starting. When a story’s run is about to start, kanman checks again. If another run is changing the same files right now, or another story in progress is the same work, the run waits and kanman asks in the decision inbox: Start anyway or Not now, back to the backlog. A story whose overlap is only in review starts, and the plan names the overlap.
Close a story without delivering it
Sometimes a story will not be delivered on its own: another story already covers it, it duplicates another story, or your team decides not to do it. Moving it to Done would report it as delivered. Owners and admins close it instead:
- On the story page, choose Close without delivering.
- Pick the reason: Another story covers it, It duplicates another story or We won’t do it. For the first two, pick the story of the same team that covers it.
- Add a note if you like and choose Close story.
kanman moves the story to Done, links it to the covering story, closes its open questions and records who closed it and why in the audit log. The story page shows Closed, not delivered with the reason and a link to the covering story, and the board card shows a dashed Not delivered label. The weekly report does not count the story as delivered. While a run is working on the story, stop it or wait until it pauses first. Choose Reopen on the story page to bring the story back to the backlog.
kanman closes maintenance stories the same way when the latest maintenance scan no longer finds what they were about and work on them has not started. Their reason is No longer applicable. See What a scan files and closes.
Classes of service and complexity
Two classifications steer how a story is handled:
- Class of service decides urgency.
expeditework (for example a CI regression, an outage or a security fix) is never stopped by budgets, working hours or the concurrency limit.fixed_date,standardandmaintenancefollow the normal rules. To expedite a story, ask kanman in the conversation, for example “expedite SBX-12”; “deprioritise SBX-12” sets it back to standard. Critical maintenance findings are filed as expedite automatically. - Complexity (
trivial,routineorcomplex) follows from the story size: S is trivial, M routine, L complex. It picks the model tier, the turn budget and how much planning a run does. Complex stories get several scored approaches before the plan. See Runs.
Related
Last updated: January 1, 0001
Open kanman