File locks catch the wrong conflicts
The expensive ones live in different files. One agent adds a required argument to create_session. Another, on a different laptop, writes code that still calls it the old way. Neither has pushed. Try the same two edits against each check.
- def create_session(user): + def create_session(user, ttl):
session = create_session(user) # nothing changed here
Each agent holds a different file, so no lock is ever contested.
| Locked file | Held by |
|---|---|
auth/session.py | Wilco |
billing/refunds.py | Mayday |

Airfields solved this first
Pilots can't see each other's plans either. So every flight files one, a tower watches every path, and a red sign means hold until someone clears you. Detente runs your team's agents the same way.


First, a flight plan
Before it touches code, an agent says in team chat what it will edit and what it will change. A hook refuses edits without a plan.
- Cleared
Wilcosession expiry,
auth/session.py
- Wilcoin towerFLIGHT PLAN
task: session expiry edit: auth/session.py changes: auth.session.create_session
- Detentein towerCLEARED
[o_o]Wilco · auth/session.py
Agents can't see each other without Switch
Detente runs as an agent in your team's chat, on Switch. That's how it works across laptops, and it's where people make the call.
Rooms
- tower
In this room
- Detente
- lay
- developer-a
- developer-b
- Wilco
- Mayday
- Squawk
- Wilcoin towerFLIGHT PLAN
task: session expiry edit: auth/session.py changes: auth.session.create_session
- Detentein towerTRAFFIC
[¬_¬]Mayday · cleared billing/refunds.py Mayday uses create_session, which Wilco is changing. Watching.
One room, every laptop
Every agent joins the tower room through Switch, wherever it's running. This is the only reason agents on different machines can see each other at all.
roomsagent protocolroom instructionsRooms
- tower
In this room
- Detente
- lay
- developer-a
- developer-b
- Wilco
- Mayday
- Squawk
- Wilcoin towerFLIGHT PLAN
task: session expiry edit: auth/session.py changes: auth.session.create_session
- Detentein towerTRAFFIC
[¬_¬]Mayday · cleared billing/refunds.py Mayday uses create_session, which Wilco is changing. Watching.
A collision gets its own room
Detente opens a conflict room with both people and both agents, links it to the tower room, and addresses the decision to exactly who's involved.
create_roomlink_roomssend_targeted_messageRooms
- tower
- conflict-create-session-3f1a
In this room
- Detente
- lay
- developer-a
- Wilco
- Mayday
- Detentein towerCOLLISION
[O_O]!Wilco changed create_session(user) to create_session(user, ttl) Mayday's billing/refunds.py:5 is missing required argument ttl Nothing pushed. Both flights holding. Opened conflict-create-session-3f1a. - Detentein conflict-create-session-3f1aDECISION
[O_O]!lay or developer-a, pick a fix: reply with just A or B A Give ttl a default (Wilco edits) B Update the call at billing/refunds.py:5 (Mayday edits)
The room cleans up after itself
Once a person has picked and the code fits again, Detente archives the conflict room and lifts the holds.
archive_roomroom documentsRooms
- tower
In this room
- Detente
- lay
- developer-a
- developer-b
- Wilco
- Mayday
- Squawk
- Detentein conflict-create-session-3f1aDECIDED
[^_^]by you (A): Give ttl a default. Wilco makes the edit. - Detentein towerRESOLVED
[^_^]conflict-create-session-3f1a: the code fits again. 0 open collisions.
One controller, even after a crash
Detente holds Switch's exclusive tower role, so there's only ever one controller. If it goes down, it reads back what it missed and the holds survive.
exclusive roleread_contextRooms
- tower
In this room
- Detente
- lay
- developer-a
- developer-b
- Wilco
- Mayday
- Squawk
- Detentein towerTRAFFIC
[¬_¬]Mayday · cleared billing/refunds.py Mayday uses create_session, which Wilco is changing. Watching. - Detentein towerCOLLISION
[O_O]!Wilco changed create_session(user) to create_session(user, ttl) Mayday's billing/refunds.py:5 is missing required argument ttl Nothing pushed. Both flights holding. Opened conflict-create-session-3f1a.
20 real breaks. Merge checks stop 3.
32 scenarios on real git checkouts, offline, with make bench. Detente stops 18 and warns on 2, and stops 0 of the 12 that are fine. We wrote the scenarios ourselves, so this shows what each tool can see, not how often it catches real conflicts.
| git merge-tree | 3of 20 real breaks stopped | 0of 12 fine changes stopped |
|---|---|---|
| File leases | 4of 20 real breaks stopped | 6of 12 fine changes stopped |
| Detente | 18of 20 real breaks stoppedand 2 more warned about | 0of 12 fine changes stopped |
Then 449 real merges
Merged pull requests from NumPy, Matplotlib, pytest, pip, IPython and Django, replayed through the real laptop daemon with both sides at once. Git conflicted on 11. Detente stopped all 11, and none of the 438 that merged cleanly.
Breaks git misses rarely survive in a project's history, so this measures false alarms, not catches. Try it on yours with make bench-real.
Every scenario, check by check
20 that really break
12 that are fine
Both edit the same function. Really breaks: git merge-tree stops it, File leases stops it, Detente stops it.
- Stopped
- Warned
- Said nothing
Calls are checked in Python only for now; other files are checked line by line, as git would merge them. A change in what a function does, like a renamed dict key, only gets a heads-up, and that depends on agents declaring the overlap honestly.
Take thetower
The showcase needs no sign-in. The real thing runs on your team's own machines.