The outcome gate and evidence

kanman never takes the executor's word for it. The outcome gate proves each story against its acceptance spec, and the evidence pack shows the proof.

Coding agents are good at saying they are done. The outcome gate is how kanman checks that they are. The executor never declares a story finished: kanman runs the gates itself, on infrastructure the executor does not control, and moves the story only when the gates pass. Everything it checked ends up in the evidence pack on the pull request.

The gates

Each gated move of a story has its own checks:

Move Gates
Refining to Ready spec_red, spec_honest: the acceptance spec exists on the protected path, runs, currently fails, and does not mock its own target
In Progress to Review diff_guard, policy_diff, spec_green_ephemeral: no executor commit touched the acceptance spec, the diff respects denied paths and size limits, and the spec passes against a freshly provisioned environment
Review to Done ci, reviewer, clean_room: CI is green, the reviewer run passed every criterion, and the spec passes on a clean-room checkout with the proof artifacts stored. Then the pull request is mergeable, or merged automatically if the policy allows it

New commits on the pull request during Review are checked again; they never move the story on their own.

kanman performs every gated move itself. When someone moves a story into Ready, on the team page or in the tracker, kanman places it in Refining first and runs the Ready gate; the card shows Checking the acceptance spec until the spec fails the way it should. Moves back to Ready from later columns are direct, because those stories already passed.

On your git host, kanman reports the result as the commit status kanman/outcome-gate. Make it a required status check in your branch protection so a pull request cannot be merged before the gate passed.

Red before Ready

A spec that already passes before any code is written does not test the new behaviour. So when kanman authors the spec from the story’s Demonstrate block, the story stays in Refining unless the spec runs and fails. The story page then shows Spec: red (expected), kanman commits the spec to the branch kanman/spec/<KEY>, and the story moves to Ready.

If kanman cannot write a working spec, it tries once more with the gate output. If that fails too, a Check failed decision asks you to improve the Demonstrate step and retry, or to keep the story in Refining.

Honest specs

A spec must test the real thing. A static check rejects specs that mock their own target, for example with route interception, MSW, nock or module mocks, before the spec ever runs. Mocks of third-party services are fine. The story stays in Refining with a reason such as Spec mocks its own target: route interception of /api/invoices.

The diff guard

The acceptance spec lives on a protected path, .kanman/acceptance/<KEY>/. Executors may never change it: the path is denied for every preset and cannot be allowed. If an implementation commit touches it anyway, or the spec folder no longer matches the version approved at Ready, the run stops with Diff guard: the acceptance spec was changed by the implementation, no pull request is marked mergeable, and the decision inbox offers Revert spec changes and retry or Reject. kanman also stamps commit authorship itself, so it knows which commits came from the executor.

Clean-room check

The final check never runs in the executor’s workspace. kanman checks out the branch fresh, restores the approved spec, provisions a new environment as your acceptance manifest describes, and runs the spec there. Traces, screenshots, videos or apply logs are stored as proof. A green spec without stored artifacts does not count.

Gate reference

Gate id Checks
spec_red The spec fails before the change
spec_honest The spec does not mock its own target
spec_green_ephemeral The spec passes in a freshly provisioned environment
diff_guard No executor commit touched .kanman/acceptance/, and the spec is unchanged since Ready
policy_diff Denied paths, max_changed_files and max_changed_lines on the final diff
clean_room The spec passes on a clean checkout in a fresh environment, with proof artifacts
ci Your CI pipeline is green. While CI is still running, kanman waits
reviewer An independent reviewer run checked every criterion against the diff
verify_local The local verify command from .kanman/verify.json passed. Not run yet, see that page

Each gate result has a verdict (pass, fail, error or skipped), a reason and links to its artifacts. Results are logged as gate_passed or gate_failed in the audit log.

The second signal: the reviewer run

Next to the spec, a reviewer run checks each acceptance criterion against the diff, with file and line references, and flags scope creep. A criterion without a code reference does not pass. The reviewer uses a model from the other vendor (a Codex model when Claude Code wrote the code, and the other way round), so the code is never reviewed by the model that wrote it. Its result per criterion is written back to the story.

When a gate fails

  1. kanman starts one automatic rework attempt and gives the executor the gate output and the reviewer’s findings (rework_attempts).
  2. If that attempt fails too, the story goes to the decision inbox as Verification failed, with kanman’s recommendation and options.
  3. Each gate has a failure budget (gate_failure_budget, 3 by default), counted over all runs of the story. When it is used up, the run is parked with Repeated gate failure and you decide what happens next.
  4. A failed diff guard is never reworked automatically; it always asks.

Problems of the test environment itself (clone, provisioning, ready check, setup) are retried quietly twice and do not count against the failure budget.

A failed gate never turns into an endless loop.

The evidence pack

When the Review gates pass, kanman writes the evidence pack. It is stored on the run, shown on the run page, and posted once as a pull request comment and once as a tracker comment. It contains:

  • the plan and the approaches considered
  • the acceptance criteria, each passed, failed or unknown, with file and line references
  • the gate results with their reasons and links to traces, screenshots and logs
  • test counts and the CI link
  • cost against budget, duration and number of attempts
  • whether outcome proof exists

The run page also lists the policy decisions taken during the run.

A shortened example as it appears on a pull request (the comment shows a status mark in front of each line):

Evidence: SBX-12 (run-7f3k)

The acceptance spec passed in a clean environment.

Plan
Add GET /invoices/export with a date-range filter and a CSV serializer.

Acceptance criteria
- Passed ac-1 Given a customer with 3 invoices in March ... (src/invoices/export.ts:42)
- Passed ac-2 Given ... (src/invoices/export.ts:61, src/invoices/csv.ts:12)

Checks
- Passed spec_green_ephemeral: Spec passed in a fresh environment [1]
- Passed diff_guard: The implementation did not touch the acceptance spec
- Passed policy_diff: The change stays within the team policy
- Passed ci: CI passed
- Passed reviewer: All 2 criteria passed review
- Passed clean_room: Spec passed on a clean checkout [1] [2]

Tests: 12 passed, 0 failed
CI: success
Cost: €0.84 / €2.00 · Duration: 11 min · Attempts: 1

The run page shows the evidence pack in your language. The comments on the pull request and in the tracker are written in English for now.

Repositories without a manifest

Without an acceptance manifest there is no spec to run. Only the Trial preset allows this, so you can start a pilot before adding a manifest. kanman then falls back to CI, the test plan and the reviewer run, records the spec gates as skipped, and the evidence pack says plainly: No acceptance spec was run, so the outcome is not proven. Review the change carefully. With any other preset, a story in a repository without a manifest stays in Refining. Add a manifest to get the full gate: see Add an acceptance manifest to your repo.

Tip

The pilot sandbox repository ships with a manifest, so you can watch the full gate in the quickstart before you set it up on your own code.

Last updated: January 1, 0001

Open kanman