Skip to content
ivralo
Sections

Docs / Developer mode

Changesets

A changeset stages a turn's edits in a separate tree, verifies them there, and then lands them all or drops them all. This page covers turning it on, the staged tree, landing and dropping, and the rule for runs nobody watches.

Turning it on

Changesets are off by default: an edit lands the moment you approve it.

WhereHow
A session/changeset on stages each turn's edits; /changeset off stops it; /changeset alone reopens the pending one
One runivralo ask --changeset "..." lands only when the checks pass; --keep-changeset stages and never lands
Every runIVRALO_CHANGESET=1 turns it on by default; ivralo ask --no-changeset turns it off for one run

ivralo doctor says whether changesets are on and names every changeset still staged.

The staged tree

In a repository, the staged tree is a git worktree under the ivralo home:

<home>/worktrees/<slug>-<hash>/changeset-<id>

It is cut from HEAD and brought up to your working tree: your uncommitted edits and untracked files are carried in on a temporary index, so your own staging area is never touched. Ignored files are not carried: a virtual environment, build output, a .env.

In a workspace that is not a repository, the staged tree is a copy of the files your request names, under .ivralo/changesets/<id>/. A request that names no file is refused before the turn runs.

What runs there

Everything the turn does to the workspace happens in the staged tree: the file tools, the shell, the Python worker, the checks, a download. A read of a file the changeset changed starts with [staged: ...], and the edit dialog's where row says the edit lands in the changeset. Each edit still asks exactly as it always does.

Three things still look at your real tree, and say so first: the language-server tools, the code index and the read surface. The symbol edits and the formatter work through the language server on your real tree, so they are refused while a changeset is open; edit_file changes the staged file instead.

Verifying in the staged tree

verify_changes runs the commands IVRALO.md declares, read from your tree, with the staged tree as the working directory and your environment shared: the shell's allowed variables and your PATH. Nothing is installed or linked. IVRALO_REAL_TREE names your real workspace for a command that needs an environment living there.

That is fast and right as long as your dependencies did not change. When the changeset touched a dependency manifest, the report says so right after its headline, and the result does not count for landing unattended. A manifest is a file the declared install command names, IVRALO.md itself, or anything you list:

# Dependencies

- uv.lock
- requirements/*.txt

Land, drop, or keep

At the end of a turn in the session, the diff viewer opens on the changeset.

KeyDoes
lLand it in your tree
xDrop it, after a question
qLeave it staged; /changeset reopens it

Your next message, while one is staged, continues the same changeset. An empty changeset is dropped with a note.

Landing first checks every file the changeset changes against the version it was staged from, by content. If you changed one of them in the meantime (edited, created or deleted it), nothing is written: the landing is refused whole with PATCH_CONFLICT, and the viewer shows both changes side by side, with only x offered. There is no merge and no guess: drop it, or keep it staged and sort it out by hand. Otherwise the changeset lands as one apply, history keeps a version of every file it replaces, and the changes panel shows one change record for it.

Dropping leaves your tree byte for byte as it was.

A changeset that a live turn has open is never landed or dropped from under it, by any client. If the process holding it is gone, ivralo changeset release <id> clears its mark so it can be landed or dropped.

Runs nobody watches

ivralo ask --changeset and the API's "changeset": "auto" follow one rule:

Outcome of the verificationWhat happens
Passed, trusted folder, edit_file in allow_toolsLanded
FailedDropped
Anything that could not be judged: nothing declared, a check refused, a changed manifest, a documents workspaceKept staged, with how to land or drop it later

--keep-changeset (the API's "keep") never lands. The JSON result of ivralo ask --format json carries a changeset object: its id, landed, dropped or kept, why, its files, where a kept one is staged, the conflicts of a refused landing, and any file of your tree that changed outside it.

From the command line and the API

ivralo changeset list            # the staged changesets (--json)
ivralo changeset show [id]       # one's files and hunks (--json)
ivralo changeset land [id]       # land it, or print both sides and exit 1
ivralo changeset drop [id] -y    # throw it away without asking
ivralo changeset release <id>    # clear the mark of a turn that no longer runs

An id may be given by its start; without one, the staged changeset is meant.

The local API (ivralo serve) has the same operations:

RouteDoes
GET /changesetsThe staged changesets
POST /changesets/{changeset}/landLand one
POST /changesets/{changeset}/dropDrop one
POST /changesets/{changeset}/releaseClear the mark of a turn that is gone

A plan is not a changeset: its waves have checkpoints and its coders their own worktrees (Plan mode). The API refuses a request that asks for both.