Fleet Review
One agent does the work, a second agent reviews it, and they go round after round until the reviewer approves or something stops the session. You attend it in the terminal and see every message before it goes out.
mur fleet review --main coder --reviewer critic "Add retry with backoff to the uploader"
mur fleet review --main coder --reviewer critic --deadline 1h --budget-usd 2 "โฆ"
mur fleet review-resume review-3f9a1c2e # continue a paused or crashed session
mur fleet list --include-review # review sessions are hidden by default
mur fleet prune-reviews --older-than 30d --dry-run
Both agents must already exist and be running. If one is not, the command names it and prints the mur agent start line that fixes it. --main and --reviewer must be different agents; names are case-insensitive.
Inside a murmur chat
The same loop runs from a chat:
/review --main coder --reviewer critic Add retry with backoff to the uploader
/review # list paused and crashed sessions
/review resume review-3f9a1c2e
--auto is refused in the chat for now. While a member's turn runs, one Esc lets it finish and pauses before the next send (โธ after turn); a second Esc cancels the turn, marks its reply discarded, not sent, and resuming sends that turn again. At the send prompt, Enter sends, typed text adds a note, and /stop stops. Ctrl+D closes gracefully: the running turn finishes and the session pauses.
A round
One round is: the main agent produces or revises, then the reviewer returns a verdict โ approve, revise or blocked โ with its findings. From round two on, the main agent answers each open finding with accept, reject or partial (a reason is required for the last two), and the reviewer gives a status for every finding it raised before: open, resolved, withdrawn or disputed.
The rules that keep the loop honest are enforced by MUR, not left to the models:
- Finding IDs come from the system.
F1,F2, โฆ are assigned in the order findings are raised. An ID the model makes up is ignored and the finding counts as new. - A malformed reply gets one retry with a hint about what was wrong. A second malformed reply stops the session as
blocked. - A finding rejected twice goes to you. When the main agent rejects the same finding a second time, the session does not stop: it waits for your ruling instead of letting the two agents argue it out. See Rulings.
approveis refused while a high-severity finding isdisputed. The refusal counts as a malformed verdict: the reviewer gets one retry to returnreviseorblocked, then the session stops asblocked. A disputed medium or low finding does not block approval.
Semi-auto: you press Enter
Every outgoing message is printed under --- next message to <agent> ---, followed by Send to <agent>? [Enter = send, q = stop, /rule drop|fix F<n> <text> = record a ruling and send this turn]. Enter sends it; q stops the session; a /rule line records a ruling and sends the turn. A tool call a member wants approved is shown the same way and needs y.
--- reviewer asks to run a tool ---
bash: ls
Allow? (4m 59s left) [y/n]
The prompt shows how long the approval window has left, recomputed each time it is asked again. Once it reaches zero it reads (window closed โ a late answer is rejected). When several calls arrive in one notification they share one deadline, so later ones show less time. If the agent's runtime is too old to report a deadline, no countdown is shown.
There is no unattended mode. The daemon never starts a review session, and MUR_FLEET_AUTORUN does not apply.
Rulings
When a finding is rejected twice, MUR prints both sides' last positions under --- F3 awaits your ruling (โฆ) --- and asks:
Awaiting ruling on F3 โ /rule drop|fix F3 <text>, /abandon, q = leave paused
| Input | Effect |
|---|---|
/rule drop F3 <why> | closes the finding as resolved |
/rule fix F3 <how> | keeps it open and makes it binding: the main agent may answer accept or partial, but a reject is sent back with a retry hint |
/abandon | ends the session with reason escalation |
q | leaves the session paused, awaiting a ruling |
/abandon is a full command on purpose; no single key ends the session from here. Anything else reprints the usage. Rulings are written to the channel, and both agents see them in their next turn, above the findings, under Binding rulings from the human (these override any finding below; do not argue them):.
You can also rule before anything escalates: type /rule drop|fix F<n> <text> at any send prompt, for any open finding. It is recorded and the turn is sent. If that finding has closed by the time the round ends, or the session ends first, the ruling is discarded and the screen says why.
Time at the ruling prompt is your time, not the agents': it is not charged to deadline or stuck, and recording a ruling resets the stuck clock.
When it stops
| Stop reason | Meaning |
|---|---|
approve | the reviewer approved |
blocked | the reviewer said blocked, or a reply was malformed twice |
escalation | you typed /abandon at the ruling prompt |
<agent> task failed: โฆ | a member's task failed or was cancelled โ for example, a tool call you denied |
stuck (round: open findings unchanged) | two rounds in a row left the open findings exactly as they were |
limit: deadline ยท limit: stuck (no activity) ยท limit: cost_usd | one of the three execution limits tripped |
stopped | q at the send prompt, or mur fleet stop <session> โ which takes effect when the turn in flight returns |
The stop screen prints the reason and every finding still open or disputed, then the channel ID it kept for audit. If the reviewer approved while a high-severity finding was still open, the screen starts with WARNING: approved with open high-severity findings: and their IDs โ a warning, not a block. There is no round cap: the limits bound the session. deadline counts execution time only โ time spent paused is never charged โ and cost_usd is the sum across both agents.
Pause, crash, resume
Pause is not stop. A stopped session is finished. A session pauses โ and stays resumable โ when you leave a ruling prompt with q, or when an agent stops answering after one retry. The second case prints Session paused. Resume with: mur fleet review-resume <session>.
A session killed outright (a closed terminal, a power cut) is crashed. review-resume treats it like a paused one: it records the crash on the channel, then continues after the last round that finished. A round half-written at the crash is run again from the main turn, so a rejection can never be counted twice. The turn that was in flight is lost โ its time and cost were never recorded โ and the resume screen says so.
Resume shows the round, the open findings and the time used. If a ruling is still owed, it goes straight to the ruling prompt. If the last thing recorded is a ruling, it asks Ruling recorded โ continue?; otherwise Paused โ continue?. q at any of these leaves it paused. It needs a terminal.
Each mur fleet review is an independent session named review-<id>. A paused one does not block a new one, and resuming one continues only that one. While a session runs, it holds a lock; a second review-resume of the same session is refused, and so is mur fleet delete on it.
Retention
Review sessions are hidden from mur fleet list; add --include-review to see them. When a session stops, its fleet definition is removed but its channel stays as the audit record. Nothing deletes it on a timer.
mur fleet prune-reviews --older-than <age> erases finished sessions idle longer than <age>. --older-than is required and has no default.
| Session state | Default | --include-paused |
|---|---|---|
| running | never | never |
| stopped, corrupted, orphaned | erased | erased |
| paused, crashed | kept | erased (recorded as stopped first) |
--dry-run lists what would go without erasing anything. To remove one session by name, use mur fleet delete review-<id>.