Skip to content

feat(protocol): file lock + branch-per-agent for concurrent session safety #19

@FScigliano93

Description

@FScigliano93

Problem

When multiple agents run simultaneously against the same repo (Claude Code + Codex + Cursor), two classes of conflict occur:

  1. Product files (code, docs) — agents edit the same file in the same branch concurrently; last-write-wins overwrites work silently, with no warning.
  2. State files (.agents/) — agents rewrite instead of append, or append conflicting state simultaneously.

The protocol mitigates class 2 via append-only rules but has no coordination mechanism for class 1, and no explicit file-level lock for either class.

Identified in a real session running Claude Code + Codex simultaneously — both agents edited shared files concurrently and one overwrote the other's work without notice. Branches don't prevent this because the conflict happens on disk before any commit.

Proposed change

Two complementary mechanisms:

1. Mandatory branch-per-agent
Each agent operates on its own branch, never directly on main. Merges happen explicitly, with conflict review.

2. File lock for .agents/ state files
New file: .agents/file_locks.jsonl (append-only, same pattern as decisions.jsonl).

Lock entry schema:

{"timestamp": "ISO-8601", "agent": "<agent-slug>", "session_id": "<session-id>", "file": "relative/path", "status": "locked|released"}

Boot procedure addition — before editing any file in .agents/, the agent:

  1. Reads file_locks.jsonl (tail + grep for the target file)
  2. If active lock exists (locked, timestamp <30min): skips file, logs in decisions.jsonl, continues elsewhere
  3. If no active lock or stale (>30min): appends locked, proceeds, appends released on completion

Known limitation: race condition if two agents check simultaneously. Not fully solvable with flat files + LLMs — mitigated in practice by natural execution intervals.

Related: #5 (append-only invariants).

Acceptance criteria

  • PROTOCOL_RULES.md defines branch-per-agent rule and file lock contract
  • CORE_RULES.md state table includes file_locks.jsonl in the project layer
  • Boot procedure includes lock check step before any .agents/ write
  • Stale lock timeout defined (proposed: 30min, aligned with active_sessions.md)
  • Known race condition limitation documented in the kernel

Open questions

  1. Branch-per-agent: mandatory or recommended? (Mandatory breaks single-branch workflows.)
  2. Lock scope: all .agents/ or a defined subset (exclude checkpoints/ and local/)?
  3. Stale timeout: 30min acceptable?

Problema

Quando múltiplos agentes rodam simultaneamente no mesmo repositório (Claude Code + Codex + Cursor), ocorrem dois tipos de conflito:

  1. Arquivos de produto (código, docs) — agentes editam o mesmo arquivo no mesmo branch ao mesmo tempo; o último a salvar sobrescreve o trabalho do outro silenciosamente, sem aviso.
  2. Arquivos de estado (.agents/) — agentes reescrevem em vez de appendar, ou appendam estado conflitante simultaneamente.

O protocolo já mitiga o tipo 2 via regras de append-only, mas não tem mecanismo de coordenação para o tipo 1, nem lock explícito em nível de arquivo para nenhum dos dois.

Identificado em sessão real com Claude Code + Codex rodando simultaneamente — ambos editaram arquivos compartilhados e um sobrescreveu o trabalho do outro sem aviso. Branches não resolvem porque o conflito acontece em disco antes de qualquer commit.

Mudança proposta

Dois mecanismos complementares:

1. Branch obrigatório por agente
Cada agente opera em seu próprio branch, nunca diretamente no main. Merges acontecem de forma explícita, com revisão de conflitos.

2. File lock para arquivos de estado em .agents/
Novo arquivo: .agents/file_locks.jsonl (append-only, mesmo padrão do decisions.jsonl).

Schema da entrada de lock:

{"timestamp": "ISO-8601", "agent": "<agent-slug>", "session_id": "<session-id>", "file": "relative/path", "status": "locked|released"}

Adição ao boot procedure — antes de editar qualquer arquivo em .agents/, o agente:

  1. file_locks.jsonl (tail + grep no arquivo alvo)
  2. Se há lock ativo (locked, timestamp <30min): pula o arquivo, registra em decisions.jsonl, continua em outros
  3. Se não há lock ativo ou está obsoleto (>30min): appenda locked, prossegue, appenda released ao concluir

Limitação conhecida: race condition se dois agentes checam o lock simultaneamente. Não é totalmente solucionável com flat files + LLMs — mitigado na prática pelos intervalos naturais de execução.

Relacionado: #5 (append-only invariants).

Critérios de aceitação

  • PROTOCOL_RULES.md define a regra de branch-por-agente e o contrato de file lock
  • Tabela de estado do CORE_RULES.md inclui file_locks.jsonl na camada de projeto
  • Boot procedure inclui etapa de verificação de lock antes de qualquer escrita em .agents/
  • Timeout de lock obsoleto definido (proposta: 30min, alinhado com active_sessions.md)
  • Limitação de race condition documentada no kernel

Questões em aberto

  1. Branch-por-agente: obrigatório ou recomendado? (Obrigatório quebra workflows de branch único.)
  2. Escopo do lock: todo .agents/ ou subconjunto definido (excluir checkpoints/ e local/)?
  3. Timeout de 30min para lock obsoleto é aceitável?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions