gitai 0.3.0 makes the storage core complete (checkpoints, garbage collection,
hydration that always finishes), makes writes faster, and gives conflicts a
full path: the server resolves what it can prove, and everything else reaches
the agent as a package with proposals.
Upgrade: read this first
- Storage core (
[graft.storage]): stop every node, upgrade every node, then
start them. The first node migrates the database and pack keys change
format; a v0.2.x node cannot run on the migrated database. There is no
downgrade past the migration: going back means restoring the database and
the bucket from a backup. A binary that finds a newer database refuses to
start and says so.
sync_timeout of 55 minutes or more now needs gc_grace above
sync_timeout + gc_margin; such configurations fail at startup with a
message that says what to raise.
- New defaults in authoritative mode: checkpoints on (hourly), garbage
collection off.
- New in every mode:
[graft.review] max_open_reviews (default 1000).
- Conflict resolvers. A resolved file must say whether it comes from a
rule (origin: "rule") or a model; anything unmarked is treated as a
model's answer. A command strategy that calls a model must set
origin = "model". graft-resolve's rerere entries written by v0.1/v0.2 are
never replayed; clear the store to reclaim them.
- Upgrade
graft-resolve and the server together. A graft-resolve of
this release gives no model's resolution to a server that does not announce
the capability proposal (and, with agree_with, hold); the file stays
unresolved and no model is called. An older graft-resolve against this
server answers without origin, so even its rules' answers become proposals
that land only if verify.command passes. If you must keep a v0.2.0
graft-resolve for a while, set inline_timeout = "0s": it ignores
rules_only and may call a model in the lane until the server detects it.
- Verification runs model-written code. With a
verify.command, every
resolution is verified on the exact tree it would land, including a model's.
Run the command in a container with no network, a read-only mount and no
credentials (RESOLVE.md has an example).
graft.land.batch.max_size is now at most 100: a larger value is rejected at
startup, since the update of a batch records the identity of every member.
- SDK:
Land retries Unavailable for merge and fast-forward lands, up
to 5 times with jittered backoff; LandResult reports the retries. Turn it
off with LandOptions.RetryUnavailable.
What is new
Storage core
- Checkpoints: a self-contained pack of a repository at a sequence.
Hydration starts from the newest one; building one never blocks a write.
- Garbage collection of covered changeset packs, superseded checkpoints,
packs of writes that died, and removed repositories, including leaks left
by older versions. Every age decision uses the database clock.
- Hydration that always finishes: rounds keep their progress and fetch 8
packs at a time; a large checkpoint is seeded in the background.
| Checkpoint pack |
v0.3.0: fresh after |
v0.2.0, same content |
| 300 MB |
3.6 s |
— |
| 1 GB |
8.2 s |
never (every round Unavailable) |
Faster writes
UserCommitFiles in 6 git processes instead of 10-15 (one reader, one
tree writer, lazy trees, exact branch resolution). 50 agents × 20 changes:
|
v0.2 |
v0.3.0 |
| p50 |
217 ms |
177 ms |
| p95 |
486 ms |
358 ms |
| p99 |
600 ms |
444 ms |
- Authoritative mode: the database commit is the durable point, so git
writes references without fsync and a background step makes them durable a
second later. SQLite, 50/100 agents: lands/min 677-972 → 1411-1673.
- Changelog group commit: concurrent writes share one fsync, in order.
Conflicts
- The conflict package: every conflicting file with its three sides, its
hunks and the reason it was not resolved; the CLI writes it to a directory
and re-lands the agent's resolution with --resolved.
- Proposals: a model's resolution reaches the agent as a proposal, with a
report of what the server checked ("drops THEIRS' change at line 40").
- A model's resolution lands by itself only if the project's tests pass on
the exact tree. Without a verify.command, it is always a proposal.
- Rules resolve in the lane, models and verification outside it. Without
a verify.command, the lane asks graft-resolve for the rules only
(rules_only) and lands their answers in the same batch as the other
changes, as 0.2.0 did, within inline_timeout (default 1s) per batch
attempt. A model's call, and any verification, run outside the lane, so
other agents keep landing meanwhile.
- Lands waiting on a hot file take turns. A land whose resolution went
stale queues for its file instead of resolving again after every landing,
so every land a rule can resolve lands. On the README benchmark with the
deterministic resolver (50 agents, 250 changes, 20% conflicting): 250 of
250 land, each in one round, 1,245-1,806 lands/min, p99 2.0-3.4 s; 0.2.0 on
the same machine: 1,871 lands/min, p99 2.1 s.
- Two models must agree (
agree_with, opt-in): a second model from
another vendor resolves the same file; if the two differ, or a composition
check finds a dropped or duplicated change, the file is held and goes to the
agent. On 487 held-out files of 13 open-source repositories
(openai/gpt-6-luna with z-ai/glm-5.3-flash): 59.8% landed, and at most
15.5% of those were judged wrong by independent reviewing models (Wilson
upper bound 20.1%). Conflicts from merged agent PRs are harder (43-52%
wrong): keep verify.command on. There is no default model; you pick the
model and the provider your code is sent to.
Not verified in this release
- S3, GCS and Azure buckets (all tests used file and memory buckets).
- Nodes on different hosts, a real power loss (simulated), non-Linux hosts,
and a downgrade (unsupported).
- The turns of lands on a hot file hold within one server process; with
several nodes landing on one branch they do not span nodes.
- With a
verify.command, resolutions on one branch are verified one at a
time, each on its own tree: the cost grows with the verification time.