lazy documentationv0.94Contents

Review and accept

flowchart LR
  Work[Task work] --> Review[Review task diff]
  Review -->|feedback| Work
  Review -->|accept| Gate[Check approvals and conditions]
  Gate --> Merge[Merge task branch]
  Merge --> Complete[Task complete]
  Complete --> Follow[Push and cleanup retries]
Review can return feedback; accept checks conditions, merges the branch, then retries follow-through work

Lazy puts a review between an agent's work and your branch, and makes the merge itself a single, recoverable step. This page explains why, and what you can rely on.

Why it exists

An agent that has just written a change is a poor judge of it, and you cannot read every diff. So lazy reviews each task before you merge it, and treats lazy accept as the one deliberate act that puts the work on its target branch. Accept is built so a crash or a failed push never leaves you with merged work that lazy still calls unfinished.

Review modes

[review] mode in lazy.toml chooses how a task is reviewed. Each task carries its own mode, and you can set it when you create or start a task:

lazy create --goal "…" --review separate
Mode Who reads the work
low_high (default) The writing agent reviews its own work in the same session, then revises
separate A reviewer in a new, read-only session
off Nobody

A review is recorded on the task in the same shape in every mode. Whether it holds your accept is set by [review] gate, which takes auto (the mode decides), always or never. A review you ask for yourself with lazy review always counts. The reasoning behind the default and the cost trade-offs are in the review paradigm; the phases of the default mode are in the low-high loop; the separate reviewer is described in agent reviews. Review turns are read-only: they report, they do not change the branch.

In Lazy Teams, a project admin sets the default on Settings → Configuration. For example:

[review]
mode = "low_high"
gate = "auto"

The writing agent reviews its work before it finishes, and the review mode decides whether a finding holds the merge.

What accept checks first

Before anything merges, accept refuses if:

The dashboard shows what is in the way before you press Accept. A task's Current review tab lists the open blocking raised items and the queued comments that have not reached the agent under "Before you can accept":

The Current review tab of a task in the dashboard. A "Before you can accept" box lists an unresolved blocking raised item and two queued comments that have not reached the agent, with the note "Accept refuses while any of these is open." Unblock, Ask, Accept and Submit buttons are below.

For protected files, the Changes tab shows a banner and puts Approve and Reject buttons on each file:

The Changes tab of a task in the dashboard. A banner reads "1 of 1 protected file not yet accepted". The file src/pricing.js is marked "protected — not yet decided; accept refuses" with Reject and Approve buttons beside its diff.

All of these happen before the merge, so a refusal changes nothing and the task keeps its status.

The merge is the commit point

Once the merge lands, the task is accepted. Lazy records that straight away (the accept reason as a comment, the session as accepted, the task as complete) and nothing that can fail runs in between.

Everything after that is follow-through: reparenting the task's children, fast-forwarding the target, pushing the parent branch, closing a pull request that was open for the task, tagging the accept, notifying the parent task, and cleaning up. Each step can be repeated safely. If one fails, the task stays complete, the steps that depend on it wait, and the daemon retries in the background. The accept command also reports what is still pending and exits non-zero, and a system message appears if it keeps failing.

If the process dies mid-accept, the task is left in merging. The daemon does not roll it back. It checks whether the work already landed and, if not, repeats the accept from the reason and approvals you gave. After three failed automatic attempts it stops, files a system message, and hands the task back to you: re-run lazy accept, or reject or close it.

Closing or rejecting

When you close or reject a task with an unfinished merge started by lazy sync, lazy aborts that merge and keeps the branch at its last commit. The result reports how many conflicts were abandoned and which commit was kept. Ordinary uncommitted edits still prevent closing or rejecting unless you explicitly allow a dirty worktree.

In each surface

Limits