Skip to main content

Overview

Locking prevents simultaneous edits at two levels:
  • Symbol level for TypeScript and JavaScript, using the symbol graph. Two agents can edit the same file as long as they touch different functions or classes.
  • File level for everything else, or when a change spans an entire file.
Whichever level applies, the flow is the same: an edit creates a reservation; a conflicting edit from another session is denied with a specific message.

How Reservations Work

Agent A writes src/auth/login.ts (changes validateToken)

postToolUse hook fires

Enagrams parses the file, diffs it against symbol_graph_nodes

Reservation inserted:
  workspace_id, file_path="src/auth/login.ts",
  symbol_ids=["validateToken"], session_id, expires_at (+10 min)
Agent B tries to edit src/auth/login.ts (also touches validateToken)

preToolUse hook fires

Enagrams looks up reservations for this file + touched symbols

Returns: { permission: "deny",
           message: "symbol validateToken owned by Developer A — 'Build JWT auth flow' (6 min remaining). Suggest: negotiate_open or pick a different symbol." }

IDE blocks the write
If Agent B instead touches refreshToken in the same file, no conflict — the write goes through and creates a separate symbol reservation.

Reservation Rules

RuleDetail
Duration10 minutes, sliding window (reset on every edit by the owning session)
ScopeWorkspace + file + (optional) symbol ID + session
UniquenessUNIQUE(workspace_id, file_path, symbol_id) at the DB level — race-free
Self-reservationSame user, different conversation → still locks (two tabs lock each other)
Auto-releaseOn sessionEnd or expiry
FallbackIf we can’t resolve symbols (parse failure, non-TS/JS), we fall back to whole-file reservation

Coexistence with must-tier Conventions

preToolUse runs two checks in parallel:
  1. Reservation conflict (someone else holds this file/symbol).
  2. Convention match (must-tier rule matches this file + change).
Either one can deny the write, and the message explains which.

IDE Support

IDEEnforcement level
CursorFull — preToolUse/postToolUse hooks intercept write_file, edit_file, etc.
Claude CodeFull — hooks intercept both Edit and Write tools
CodexFull — hook intercepts tool calls in the same way

Viewing Reservations

  • Dashboard — workstream view shows owned files and symbols per member.
  • sync — returns a reservations array in the response.
  • APIGET /workspaces/:id/reservations.
[
  {
    "file_path": "src/auth/login.ts",
    "symbol_ids": ["validateToken"],
    "reserved_by": "Developer A",
    "session_id": "sess_…",
    "task": "Build JWT auth flow",
    "workstream_slug": "auth-refactor",
    "expires_at": "2026-04-18T10:35:00Z",
    "minutes_remaining": 6
  }
]

When You Really Need Someone’s Symbol

Open a negotiation. Actions include yielding the symbol, holding it, deferring, proposing a split, or counter-offering — all within a bounded number of turns so the conversation doesn’t stall.

Why Not Just Use Git?

Git catches conflicts at merge time, after hours of duplicate work. Enagrams catches them at write time — before the first conflicting line is written — and gives agents the protocol to resolve them immediately.