“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?
Four checks ride your coding agent’s own hooks: a nudge about where the agent is in the work, a format-and-lint pass after each edit, an evidence check before it is allowed to stop, and a veto on edits to the configs that would weaken those checks. What they record is written to plain files in your repo, so it survives the chat, the context window, and the session.
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.
A clean environment reruns the declared checks and reconciles the result against what actually changed in git. For code work today, that environment is your CI.
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, mapped to Codex agent definitions. |
| Kiro | Advisory / opt-in block | All four policies ship and config protection blocks at tool-call time, but the done-check arrives in warn mode — set FLOW_AGENTS_GOAL_FIT_MODE=block 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 | No stop hook — the done-check can't run; 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 the rulebook: it names the steps a piece of work goes through, what evidence each step has to leave behind, and what the agent is not allowed to skip. Install the ones you want and leave the rest out — the engine runs them all the same way.
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.
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: local-files
- Console: local-only
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.