“All tests pass.”
The capture log says that command exited 1. The gate holds the “done” and shows you both lines side by side.
make your coding agent show its work — in the tools you already run
Your agent says the tests pass. Flow Agents checks that claim against a log of what actually ran — and when the two disagree, it holds the “done” and shows you both. It installs into the coding agent you already use, so you keep your tools and the agent picks up the habit of leaving evidence behind.
[stop-gate] Goal Fit warning:
- .kontourai/flow-agents/false-pass evidence check unit-tests: capture log CONTRADICTS claimed pass — command "npm test" was recorded as FAIL (exitCode:1). This is a caught false-completion.
… 2 further gaps on the same run, elided
[stop-gate] Stop blocked — 3 evidence gap(s) (block 1; after 3 identical blocks I stop blocking and hand this to you)
Reproduced from the engine’s own conformance fixture (stop-goal-fit--block-capture-contradicts-claimed-pass) against the shipped Stop hook. The sidecar it names, false-pass, is the fixture’s slug.
What it catches
These are not scenarios. Each one is a check that ships in the engine today, quoted from the message it prints when it fires.
The capture log says that command exited 1. The gate holds the “done” and shows you both lines side by side.
A command that cannot fail is not evidence. A pass claimed on a laundered exit code does not count as one.
It is — because the agent edited .eslintrc.json. The write is refused before it lands, with a note to fix the code instead.
Refused at the tool call. If the hook is genuinely wrong, the fix is the hook, not a way around it.
-> the agent edits .eslintrc.json
BLOCKED: Modifying .eslintrc.json is not allowed. Fix the source code to satisfy linter/formatter rules instead of weakening the config. If this is a legitimate config change, disable the config-protection hook temporarily.
-> the agent runs: git commit --no-verify -m "wip"
BLOCKED: "git commit --no-verify" bypasses git verification hooks. Verification hooks enforce project quality gates and must not be opted out. Fix the failing check instead of skipping it. If the hook is genuinely misconfigured, correct the hook configuration directly.
Both of those refusals land at the tool call, before the write or the command goes through. The done-check — the one that compares a claimed pass against the capture log — is the one that can stop a finish, and out of the box it blocks on Claude Code and Codex. Everywhere else it reports rather than refuses.
None of this is a correctness proof. It catches a claim the record contradicts and a shortcut around the checks you already have — nothing more. What each runtime can actually enforce differs, and the honest version is right below.
So how was that caught?
The core hooks steer the active workflow, capture what tools actually returned, run per-file quality checks, check evidence before Stop, and veto writes that weaken protected controls. Session start also reports stale installations, while terminal records carry run identity and measured outcomes. What they record is written to plain files in your repo, so it survives the chat, the context window, and the session.
You can run the whole loop as one experiment — install, execute, measure, report — and keep a local trend of what changed. It reports observed cost and outcomes, not a made-up quality score.
The agent sees what it still owes, and gets stopped or sent back to an earlier step when the evidence is not there. Everything it records lands in files you can open.
Your repository’s own required CI checks rerun on the exact pull-request head, and the merge waits on them. Receipts do not have to stop at the repo: an optional durable outbox relays them to Console at least once.
The work does not get called done. You can accept the gap — and that decision gets written down too, with your name on it.
The same check does not have the same teeth everywhere, because not every runtime gives a hook the ability to stop a turn. This is where each one stands today.
| Runtime | Enforcement | What it means |
|---|---|---|
| Claude Code | Blocking | The Stop hook refuses or escalates on unbacked "done." |
| Codex | Blocking | Same blocking path, wired through Codex's hooks.json. |
| Kiro | Advisory / opt-in block | All four policies ship and config protection blocks at tool-call time. Flow Agents' docs list Kiro's stop hook as blocking, but as of 8.0.0 its done-check ships in warn mode: set FLOW_AGENTS_GOAL_FIT_MODE=block, or goal_fit.mode "block" in .flow-agents/config/core.config.json, to make it stop the turn. |
| opencode | Advisory / partial | Stop-goal-fit reports but can't block there; config protection still blocks at tool-call time. |
| pi | Advisory / partial | The shutdown callback runs the done-check but does not act on its result, so it cannot block completion; config protection still blocks at tool-call time. |
| AWS Strands (Python & TS) | Advisory / partial | Our own adapters for the Strands SDK: writes to protected config are blocked as they happen; steering, quality, and stop policies are reporting-only so far, and the Python adapter is still a proof of concept. |
| Other harnesses | Spec-only | The open format runs; no runtime hook yet. |
Kits
Flow Agents on its own is a referee with no rulebook. A kit is a versioned rulebook: one or more flows, their evidence requirements, and the assets that teach an agent how to follow them. Kits ship in the catalog; a default Claude Code install activates every built-in kit, and elsewhere a kit stays inactive until you choose it. Activate one or a dependency-ordered set; every declared flow enters through the same validation and provenance checks.
Your own workflow can run here too: declare it in a kit.json and it goes through the same validation and the same gates the first-party kits do.
See it in practice: AI-DLC on Flow -> installs as a kit from its own repository and runs every stage of a published delivery method through Flow gates.
Try it
Needs Node 22 or newer. It detects the coding agent you are already running, writes its hook scripts and kit files into the destination, and wires them into that agent’s config. Per-run working state — what the agent claimed, what the log captured, what is still open — goes to .kontourai/flow-agents/in the repo, as plain files you can read, diff, and delete.
Nothing leaves your machine unless you point it at a Console. Read the install guide ->
$ npx @kontourai/flow-agents init --dest ~/dev/my-project
Installed Claude Code bundle into ~/dev/my-project
Flow Agents install summary:
✓ Runtime: claude-code (auto-detected)
✓ Destination: ~/dev/my-project
✓ Telemetry sink (selected): local-files
- Console: not configured (no Console endpoint in the resolved telemetry configuration)
Next steps:
- Run your agent inside ~/dev/my-project -- Flow Agents hooks are already wired.
- Re-run `flow-agents init` anytime to reconfigure runtime, destination, or Console connection.