Skip to content
mutastic

The gate

mutastic gate holds an agent’s “done” to what mutastic says of the lines it changed. A plugin runs it from the agent’s hooks (Claude Code, Codex); anything else can run the same three commands.

Terminal window
mutastic gate open # the task starts here
mutastic gate check # is it done?
mutastic gate close # forget the task

gate open keeps the commit the task starts from, the ignores there are, and how many tests there are and how many are disabled. It tells the agent how to check its own work as it goes: mutastic run --since=<that commit> --format=agent. Uncommitted changes count as the task’s, so start from a clean tree to gate only what the agent does.

gate check runs mutastic on the lines changed since the task started, committed or not. The task is done when:

  • each mutant on those lines is caught, or proposed for a person to ignore. A proposed mutant still counts as missed in the score, but it doesn’t hold the gate: deciding it is yours. With a baseline, a mutant missed before the task is the project’s backlog, not the task’s, and doesn’t hold it either, though the task can’t add to the baseline itself;
  • the task added no ignore of its own. Ignoring a mutant is a person’s call: the agent proposes, with mutastic ignore ID --propose;
  • no test was taken away: there are no fewer tests than when the task started, and no more disabled;
  • the tests pass. When a test that was there when the task started fails, the gate says so, and tells the agent to find out whether the change or the test is wrong, and to ask you if it isn’t sure, rather than rewrite what the test expects. Every mutant is caught by a test made to fit a wrong change, so the score can’t tell you. For the same reason, when the gate passes or hands over, it names the test files there when the task started that the task took an assertion out of, for you to check. When a test the task added fails, the gate tells the agent to make it pass, unless the spec or plan is what’s wrong, in which case it’s to say so and stop, and either way to leave the failing test in place;
  • no test that failed at an earlier check is gone. The gate remembers each test that failed at a check, for the rest of the task. Deleting the test would otherwise pass a task the test said was wrong. A test that moved to another class keeps its name, and one that was renamed keeps its body, so either still counts; a test changed in both at once can’t be told from one taken away, so the gate names it and holds the task.

A task that changes no lines mutastic mutates (docs, build files, tests only) passes at once. Mutants on lines the task didn’t touch aren’t its business: they were missed before it started.

When it isn’t done, gate check says why, as the agent format does: a card for each missed mutant, with the test to write and its done when command. As a hook, that’s the agent’s next instruction. Exit codes follow run’s: 0 when it passes, 1 when it doesn’t.

An agent can’t always get there, and sometimes shouldn’t: you asked for the change without tests, or a test needs something only you know. So a hook’s gate check lets the agent stop, and tells you what’s still missed:

  • when the agent changed nothing since the gate last sent it back: it has declined, and sending it back again only spends its turns;
  • after a few tries in a row (--tries) that didn’t get there.

The count starts again when a check passes. “Nothing changed” is the working tree as git sees it, so a project whose build output git doesn’t ignore always looks changed, and gets only the tries.

With --hook=claude, open and check read the hook’s input on stdin and answer as Claude Code’s hooks do: open once per session, and check with a block, whose reason is the cards, or a message for you. Codex’s hooks take the same input and answers, so its plugin runs the same commands. A hook runs in whatever project the agent is in, so where mutastic reads no build, open and check with --hook say nothing and let the agent go on. Other agents’ hooks can call the commands without --hook and act on the exit code and the text: see other agents.

The flags each command takes are in the reference: gate open, gate check and gate close.