Staleness and conflicts

~3 min read

Staleness and conflicts

A proposal is stale when the file it targets has changed since the proposal was created. This page covers when that happens, how Lettuce surfaces it, and how to resolve it.

How staleness is detected

Every proposal captures the file’s before content at the moment of creation. At accept time, Lettuce re-reads the file and compares it to that captured content:

There’s no per-proposal content hash and no stale flag in the queue — staleness is computed fresh from disk at the moment you accept.

What happens on a stale accept

Lettuce refuses the write and surfaces the reason (contentDrifted, targetAlreadyExists, sourceMissing, or destinationOccupied). There is no merge UI — the proposal is simply not applied. From there you can:

  1. Reject — discard the now-irrelevant proposal.

  2. Re-ask the agent — have it re-read the current file and re-propose with fresh context. (An agent that polls list_my_proposals and reconciles against the live file does this on its own.)

Why proposals go stale

Common causes:

Agent self-healing

Agents that periodically check their queue can reconcile against the live file and clean up:

my_props = client.tools.list_my_proposals()
for p in my_props["proposals"]:
    # Re-read the current file and decide whether the proposal still applies...
    fresh = client.tools.read_note(path=p["path"])
    client.tools.withdraw_proposal(id=p["id"])
    # ...then re-issue the write (it queues a fresh proposal against current content)...
    client.tools.apply_edits(
        path=p["path"],
        edits=rebuild_edits(fresh["content"]),
    )
    # ...or just withdraw if it no longer applies.

list_my_proposals takes no arguments — it returns every pending proposal authored by the calling key (id, tool, path, operation, timestamp). withdraw_proposal cancels one by id and refuses to touch another agent’s queue. A schedule running this every few hours keeps queues clean. See Recipes/03 Tag curator for a working example.

Conflict between two proposals

When two agents propose overlapping changes to the same file:

Practical: review proposals oldest-first unless you have a reason not to, so each accept’s before is more likely to still match.