.kanman/acceptance.json
Every key of the acceptance manifest: how kanman starts your app, waits for it, and runs the acceptance spec of one story.
The acceptance manifest tells kanman how to prove a story in your repository. It lives at .kanman/acceptance.json in the repository root. With it, kanman can run the outcome gate: it writes an executable acceptance spec for each story, checks that the spec fails before any code exists, and checks that it passes on a clean checkout after the change.
kanman stays repository-agnostic. The manifest declares the commands; kanman runs them in a fresh environment. Secrets stay in your CI settings and never go into the manifest.
For a step-by-step introduction, see Add an acceptance manifest to your repo. For the local verify command, see .kanman/verify.json.
Example
This is the manifest of the public demo repository kanman-ai/pilot-sandbox, a small TypeScript service with Playwright specs:
{
"version": 1,
"provision": {
"type": "docker_compose",
"file": "docker-compose.acceptance.yml",
"up": "docker compose -f docker-compose.acceptance.yml up -d --build --wait",
"down": "docker compose -f docker-compose.acceptance.yml down -v"
},
"ready_url": "http://localhost:3000/api/invoices",
"ready_timeout_seconds": 120,
"setup": "npm ci && npx playwright install --with-deps chromium",
"run": {
"command": "npx playwright test",
"spec_arg": ".kanman/acceptance/{KEY}/",
"env": {
"BASE_URL": "http://localhost:3000"
}
},
"spec_dir": ".kanman/acceptance/{KEY}",
"artifacts": [
"test-results/**/trace.zip",
"test-results/**/*.png",
"test-results/**/*.webm",
"test-results/results.json",
"playwright-report/**"
]
}
For story SBX-12, kanman runs npx playwright test .kanman/acceptance/SBX-12/ against the app started with Docker Compose, and stores the trace, screenshots, video and JSON report as proof.
Top-level keys
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
version |
number | yes | Always 1. |
|
provision |
object | yes | How to start a fresh environment for the spec. See provision. | |
ready_url |
string (URL) | no | kanman polls this URL every two seconds after provisioning and continues once it answers with a 2xx or 3xx status. Leave it out if your provision command only returns when the app is ready (for example docker compose up --wait). |
|
ready_timeout_seconds |
integer | no | 300 |
How long kanman waits for the environment to become ready. Maximum 900. |
setup |
string | no | Shell command run once in the checkout after the environment is ready and before the spec, for example installing dependencies and browsers. | |
run |
object | yes | How to run the spec. See run. | |
spec_dir |
string | no | .kanman/acceptance/{KEY} |
Folder of one story’s spec. {KEY} is replaced with the story key. |
artifacts |
array of strings | no | ["test-results/**"] |
Glob patterns of files kept as proof (traces, screenshots, video, reports, apply logs). They are linked from the evidence pack. The first entry that is a plain path ending in .json (no wildcards), for example test-results/results.json, is read as the framework’s JSON report. |
framework |
string | no | playwright |
Test framework of the specs: playwright, vitest, jest, pytest or other. kanman uses it to write specs in the right style and to read results. With other, only the exit code counts. |
Unknown keys are ignored, so a manifest written for a newer version keeps working with an older runner.
provision
provision.type selects one of two forms.
Docker Compose
Use this for applications that start as one or more containers.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
type |
string | yes | docker_compose |
|
file |
string | yes | Path of the Compose file, relative to the repository root. | |
up |
string | no | docker compose -f <file> up -d --build --wait |
Full command that starts the environment. The default returns once the health checks pass. |
down |
string | no | docker compose -f <file> down -v |
Full command that removes the environment after the run. |
service |
string | no | Name of the main service, for your own reference. kanman accepts the key but does not use it. |
Apply
Use this for repositories that are not a running app, for example infrastructure or configuration. The proof is the apply log plus whatever your spec checks.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
type |
string | yes | apply |
|
command |
string | yes | Command that creates the environment, for example a plan and apply against a throwaway workspace. | |
down |
string | no | Command that tears it down again. |
Example for an infrastructure repository that checks its modules against a local test stack:
{
"version": 1,
"provision": {
"type": "apply",
"command": "make test-env-up > apply.log 2>&1",
"down": "make test-env-down"
},
"ready_timeout_seconds": 600,
"setup": "make tools",
"run": {
"command": "pytest",
"spec_arg": ".kanman/acceptance/{KEY}/",
"env": {
"TEST_ENV": "acceptance"
}
},
"spec_dir": ".kanman/acceptance/{KEY}",
"framework": "pytest",
"artifacts": ["apply.log", "reports/**/*.xml"]
}
run
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
command |
string | yes | Command that runs specs, for example npx playwright test. |
|
spec_arg |
string | no | Argument appended to command to run only one story’s spec. {KEY} is replaced with the story key. |
|
env |
object of strings | no | {} |
Extra environment variables for the spec run. Only plain values, never secrets. |
The full command for one story is command plus a space plus spec_arg with {KEY} filled in.
kanman always sets CI=true and KANMAN_STORY_KEY (the story key) for the run. Values in run.env win over these.
Tip
Keep the trailing slash in spec_arg when you pass a folder. Playwright treats the argument as a pattern, so .kanman/acceptance/SBX-1 would also match SBX-12.
The {KEY} placeholder
{KEY} is the story key kanman shows on the story page, made of the team’s key prefix and a number, for example SBX-12. It is replaced in spec_dir and run.spec_arg.
The protected spec folder
Everything below .kanman/acceptance/ belongs to kanman’s spec author:
- kanman writes the spec from the story’s Demonstrate block before the story moves to Ready. The files must stay inside the story’s own folder (
.kanman/acceptance/<KEY>/). - Once the spec has failed as expected, kanman commits it to the branch
kanman/spec/<KEY>. The implementation branch starts from there, so the spec ships with the pull request. - The implementation never edits these files. Every preset denies
.kanman/acceptance/**to the executor, and the diff guard stops the run if a commit touches the folder anyway or the folder differs from the version approved at Ready. - A spec must not mock its own target. Network interception, MSW, nock and module mocks of the behaviour under test make the spec invalid.
How kanman uses the manifest
| Moment | What kanman runs |
|---|---|
| Before Ready | provision, wait for ready_url, setup, then the new spec on your default branch. It must run and fail. |
| In Progress to Review | The same in a freshly provisioned environment against the implementation branch, with the approved spec restored. The spec must pass. |
| Review to Done | The same on a clean-room checkout (never the executor’s workspace) in a fresh environment. The spec must pass and artifacts are stored as proof. |
| After a deployment | When your GitHub repository reports a successful deployment with an environment URL, kanman runs the specs of stories merged in the seven days before it against that URL, without provisioning. A failure is filed as a regression on the team’s intake. |
Each run gets a fresh checkout in its own directory. down runs after each of these, also when the spec fails. One run (provisioning, setup and spec together) may take at most 30 minutes.
A spec that does not compile, finds no tests or crashes the test runner counts as an error, not as red. Problems before the spec starts (clone, provisioning, ready check, setup) count as environment failures; kanman retries them quietly before it asks you.
Validation errors
kanman reads the manifest from your default branch when a story moves toward Ready. If it is missing or invalid, the story stays in Refining and the story page shows The repository has no .kanman/acceptance.json, so no acceptance spec can run or The acceptance manifest is invalid: followed by the reason. Common causes:
| Problem | Fix |
|---|---|
version must be 1 |
Add "version": 1. |
provision.type must be docker_compose or apply |
Use one of the two forms. |
ready_timeout_seconds is above 900 |
Lower it or make up return only when the app is ready. |
run.command is empty |
Add the command that runs your specs. |
Repositories without a manifest can only run on the Trial preset; with any other preset the story stays in Refining. kanman then falls back to CI, the test plan and the reviewer run, and the evidence pack says plainly that no outcome proof exists.
Related
- The outcome gate and evidence
- Add an acceptance manifest to your repo
- .kanman/verify.json
- Policy settings (
require_acceptance_spec)
Last updated: January 1, 0001
Open kanman