From install to a gate in CI
Your first sweep
A sweep runs where your simulator is. It makes your system worse on purpose - a fault from a catalogue, through your adapter - and records which scenarios' own checks object. Start with the pre-flight: it finds the adapter mistakes that would otherwise be scored as results.
# is the adapter ready to measure anything, and can this budget detect a fault? mutational doctor --suite suite.json --baseline 3 --trials 5 -- ./run.sh '{scenario}' # sweep, keep every run, post the result to this workspace export MUTATIONAL_TOKEN=mutational_... mutational stale --suite suite.json --baseline 3 --trials 5 \ --record history.jsonl --record-runs runs.jsonl \ --fingerprint "$(git rev-parse --short HEAD)" \ --post -- ./run.sh '{scenario}'
It appears under Sweeps. What is posted is a summary - scenario names, scores, which faults each caught - and the recording with everything your adapter printed stripped out.
The adapter contract
One script that runs one scenario. Mutational knows nothing else about your stack.
| What | Means |
|---|---|
$1, MUTATIONAL_SCENARIO | the scenario to run |
MUTATIONAL_MUTANT | the fault to inject, as one flat JSON object - or the literal null for a clean run |
MUTATIONAL_SEED | a seed, so a run is reproducible |
| exit 0 | the scenario passed |
| exit 1 | the scenario failed - it caught this fault |
| exit 3 | the fault means nothing in this scenario; it leaves the denominator |
| anything else | the harness broke. Never counted as a catch |
MUTATIONAL_REASON: ... | optional, one line: on exit 1 the name of the check that failed |
The mistake that matters most: an uncaught exception in a Python adapter exits 1, which reads as a catch. Wrap your entry point and exit 2.
A gate in CI
Post every build's sweep, then ask whether this build lost coverage. The gate exits 1 when a scenario stopped catching something it used to, and 2 when nobody can say - an unanswered question is never a pass.
# .github/workflows/sim.yml, after your sweep step
- run: |
mutational gate --url \
--suite-name suite.json --fingerprint "$(git rev-parse --short HEAD)"
env:
MUTATIONAL_TOKEN: ${{ secrets.MUTATIONAL_TOKEN }}Record and replay
--record-runs runs.jsonl keeps every simulator run. Replay it anywhere into the full report, with no simulator - on a laptop, in CI, or in the Playground, where it never leaves the tab.
mutational stale --replay runs.jsonl --suite suite.json --baseline 3 --trials 5
A recording answers for the settings it was made with. Ask for others and the replay says how many runs are missing, and exits 2.
Connect an agent (MCP)
mutational mcp serves everything over the Model Context Protocol, on stdio. The rule it enforces is the product: a model may propose anything, and only a sweep accepts it.
# .mcp.json
{ "mcpServers": { "mutational": {
"command": "mutational",
"args": ["mcp", "--project", "mutational.project.json"] } } }Give the agent an agent token from Tokens, not a full one. It can add to your history and read the gate; it cannot delete a sweep or replace one with a sweep that catches less - so it cannot rewrite the history its own work is judged against.
The loop, from the cloud
Everything the command line does beside your simulator can be driven from here: a worklist, a model proposing scenarios, campaigns on your own workers, accept, and renders of what earned its place. Your simulator does not move, and neither does your scenario source.
1. Say what the project shares, and push it
Add a cloud section to the project file, then push. It says what it is sending, and to which host, every time.
# mutational.project.json "collector": "", "cloud": { "records": true, # post each sweep's full record: which check each caught defect failed through "format": "scenario-format.json", # the closed, bounded vocabulary a model may write in "generated": "generated.json" } # the ONE file approved scenarios are written to export MUTATIONAL_TOKEN=mutational_... mutational project push --project mutational.project.json
Sent: the fault catalogue, facts with each scenario's source removed, the format, and digests of the suite and the adapter. Refused by the collector if anything sends them: scenario source, a command line, an environment, a path.
2. Publish a scenario format
A model is held to it, in the cloud and again on your worker. Objects list their fields and have no others, numbers have bounds, strings have a pattern or an enumeration, arrays have a ceiling; an oracle names only checks your adapter can evaluate. A format that is looser than that is refused when you push it.
3. Connect your keys, start a worker
Integrations takes an OpenRouter key (proposals), a World Labs key (renders) and optionally a TypeSafe key (filing field notes). Then, next to the simulator:
mutational worker --cloud --project mutational.project.json
It dials out - nothing has to reach it - and runs the adapter its own project file pins. A campaign is a system's name and bounded numbers, never a command.
4. Propose, approve, sweep
On a project's page: ask for scenarios, approve the ones you want run, and queue a sweep. The worker checks each against the format in its own checkout, writes it to the generated file, describes the corpus again, sweeps and posts. accept then answers from that sweep - earns its place, duplicate, catches nothing - and that is the only thing that says so. The autopilot does the same round inside a budget you give it.
5. Or let an agent do it
# a remote MCP server, with an AGENT token
{ "mcpServers": { "mutational": { "type": "http", "url": "/v1/mcp",
"headers": { "Authorization": "Bearer mutational_..." } } } }The same tools the page uses. An agent can read, ask for proposals and queue campaigns. It cannot approve a proposal, switch the autopilot on, spend on a render, delete anything, or replace a build's sweep with one that catches less.
Limits
The free plan, while in beta.
A sweep refused for a limit is not stored, and the refusal says when the month starts again. It is still on the machine that ran it: post it later from its recording with --replay ... --post.
Questions
Do my scenarios leave my machine?
No. Scenario source is never sent by anything here, and the collector refuses it by name. What you post is a summary and, if you ask for it, a recording stripped of what your adapter printed.
How do I delete something?
DELETE /v1/sweeps/<id> with a full token removes a sweep and its recording. Settings removes the whole workspace.
Something else?
Write to admin@mutational.in.