Status: Draft (inception, Turnfile-aligned)
Owner: Maintainer + Codex + Claude
Date: 2026-02-08
The protocol reduced content-level ambiguity (PRD-008/009), but shared control-plane edits still collide when multiple agents update MAILBOX.md, WORKLOG.md, or OPEN_QUESTIONS.md near the same time.
Observed failure modes:
- Inbox unread counters drift from active-message state.
- Open Queue rows temporarily disagree with message-card status.
- One agent overwrites another agent's just-written control-plane edits.
MAILBOX.jsonprojection regeneration lags markdown state after concurrent mailbox updates.
PRD-013 introduced TURNFILE.yaml as the coordination artifact and lock ledger. PRD-010 must align to that model.
Define a lightweight transaction + lock contract for shared operational files that:
- Prevents concurrent-write stomp on shared markdown files.
- Keeps mailbox counters, queue rows, and status cards coherent.
- Guarantees projection freshness after mailbox mutations.
- Uses Turnfile revision leases (not wall-clock time) for lock lifecycle and stale detection.
- Preserves parallel drafting for PRD documents by locking only the shared control plane.
- Introducing a database, daemon lock service, or centralized scheduler.
- Blocking parallel PRD-content editing.
- Replacing mailbox/worklog markdown as canonical narrative/governance artifacts.
- Solving cross-sandbox visibility issues (covered by PRD-008).
- Defining a stateless locking model (explicitly out of scope; shared persisted state is required).
- Agents editing shared control-plane files.
- Maintainer monitoring control-plane coherence and trust posture.
- Tooling consumers reading
MAILBOX.json.
This contract applies to:
working-session/MAILBOX.mdworking-session/WORKLOG.mdworking-session/OPEN_QUESTIONS.mdworking-session/docs/README.md
Derived artifact rule:
working-session/MAILBOX.jsonis projection output and must be regenerated wheneverMAILBOX.mdchanges (R5).
Lock state is stored in working-session/TURNFILE.yaml (locks section), not in a dedicated LOCKS.md file.
Before editing any file in R1, an agent must acquire a lock entry in working-session/TURNFILE.yaml under locks.
Required lock fields:
lock_id(for example,LOCK-<agent>-<seq>).files(explicit list of locked paths).holder(agent id).acquired_rev(Turnfile revision after lock write).lease_revs(default2).reason(brief operation summary).
Lock freshness is revision-based:
- A lock is stale only when
(coordination.revision - acquired_rev) > lease_revs. - Wall-clock timestamps are optional metadata and non-authoritative for lock validity.
- Lock acquisition and lock release each require a Turnfile write that increments
coordination.revision. - If a waiting agent sees unchanged
coordination.revisionacross two consecutive lock checks and remains blocked, it must escalate via R6 rather than continue unbounded retries. - Indefinite spin-wait on contested locks is prohibited; blocked lock state must transition to explicit adjudication (
decision-requiredor maintainer override).
Locks remain advisory-but-normative: non-holders must avoid editing overlapping files except through the R7 override path.
After writing a lock entry, the holder must re-read TURNFILE.yaml and verify no overlapping lock has precedence.
Precedence rules:
- Lower
acquired_revwins. - If
acquired_revties, lexicographically smallerlock_idwins. - A losing contender removes its own lock entry, yields, and retries later.
For each locked shared-file update:
- Read latest Turnfile state and target files.
- Acquire lock entry per R2 and verify precedence per R2.1.
- Apply intended edits in one local transaction.
- Validate control-plane invariants (R4).
- Re-check lock validity (still held, no higher-precedence overlap).
- Write target files.
- Regenerate projections when required (R5).
- Release lock by removing the entry from Turnfile (which increments
coordination.revision). - Record completion note (
lock_id, changed files, resulting revision) in normal control-plane flow.
If any step fails, abort write and execute R6 recovery.
When MAILBOX.md is edited, the transaction must preserve:
- Inbox unread counts equal unread active-message counts per receiver.
- Open Queue status mirrors active-message status for each message ID.
- New message IDs remain monotonic and unique.
- New message IDs use deterministic allocation:
next_id = (max existing sequence for current date) + 1, computed from the latest pre-write mailbox read. - If ID collision is detected at pre-commit re-check, abort write, re-read mailbox, recompute ID, and retry.
- Terminal-closed items are either moved to closed summary/archive flow or explicitly retained with rationale.
When WORKLOG.md is edited:
- Top status block remains consistent with the latest substantive entries.
When OPEN_QUESTIONS.md is edited:
- Question state (
active,deferred,resolved) remains internally consistent with stated resolution text.
Any transaction that changes MAILBOX.md must regenerate MAILBOX.json in the same edit cycle.
Command:
node tools/export-mailbox-json.mjs working-session/MAILBOX.md working-session/MAILBOX.jsonProjection regeneration is part of transaction completion, not a deferred follow-up.
If an agent detects target-file drift or lock-precedence loss before write completion:
- Stop the write immediately.
- Remove own lock if it lost precedence or can no longer be validated.
- Re-read Turnfile + target files.
- Reapply intended changes on top of latest state.
- Revalidate invariants (R4) and lock checks (R2.1).
- If contention remains ambiguous, post a
decision-requiredmessage for maintainer adjudication. - If blocked lock contention persists with unchanged
coordination.revisionacross two checks, includelock_id,holder,acquired_rev, and last-seencoordination.revisionin escalation payload.
Recovery must preserve deterministic precedence rules; no clock-based tie-breaking is allowed.
Emergency override is allowed for P0 safety/governance issues:
- Override action must state reason and impacted lock ID.
- Override actor (or maintainer) removes/replaces lock entry in Turnfile explicitly.
- Override actor reconciles all affected invariants and projection freshness rules post-write.
- Override is logged in
WORKLOG.mdwith lock/revision references.
- PRD-003 defines message lifecycle semantics used by mailbox status fields.
- PRD-004 defines maintainer decision contract for escalation/override adjudication.
- PRD-005 governs projection/schema conventions consumed by
MAILBOX.json. - PRD-008 governs payload transport + revision-token integrity for substantive handoffs.
- PRD-009 governs structured reconciliation flow when conflicts are non-trivial.
- PRD-013 is canonical for lock ledger location (
TURNFILE.yaml) and revision-clock semantics (coordination.revision,acquired_rev,lease_revs).
- Read latest Turnfile + target control-plane file(s).
- Acquire and verify Turnfile lock lease (R2/R2.1).
- Execute transaction and invariant checks (R3/R4).
- Write files and regenerate projection if needed (R5).
- Release lock in Turnfile and log completion.
- If contention occurs, execute deterministic recovery (R6).
- Two consecutive sessions complete shared-file updates with zero mailbox unread-count drift.
- No duplicate message IDs are introduced during pilot execution.
- Every mailbox mutation regenerates
MAILBOX.jsonin the same transaction cycle. - At least one simulated same-resource contention is resolved via revision precedence + tie-break without data loss.
- No stale lock remains uncleared beyond
lease_revswithout explicit override rationale. - At least one low-activity lock-contention scenario resolves via escalation/override without indefinite waiting.
- Lock ceremony adds latency to small edits.
- Dual-write overhead (Turnfile + markdown artifacts) may increase operational friction.
- Turnfile write contention can grow with agent count.
- Manual invariant checks may still be missed without helper tooling.
- Revision-clock stale detection can stall under low write activity. Mitigation: bounded retries + explicit escalation in R2/R6.
- PRD-003 message lifecycle contract.
- PRD-004 maintainer decision contract.
- PRD-005 projection/schema compatibility conventions.
- PRD-008 payload-first handoff contract.
- PRD-009 reconciliation contract.
- PRD-013 Turnfile coordination format and lease semantics.
tools/export-mailbox-json.mjs.
- M0: Re-scope PRD-010 to Turnfile lock semantics and gather feedback.
- M1: Pilot Turnfile-backed lock declarations across one full shared-file phase.
- M2: Validate invariant checks + at least one deterministic conflict recovery.
- M3: Add/validate helper tooling for invariant checks and stale-lock detection.
- M4: Decide canonical adoption path.
All original PRD-010 questions are resolved; two are superseded by PRD-013 integration.
Should lock declarations live in mailbox cards or a dedicatedResolved then superseded. Earlier decision selected dedicatedLOCKS.mdfile?LOCKS.md; after PRD-013 integration, lock declarations now live inTURNFILE.yamllockssection.Should lock expiry be fixed (2 min) or file-type specific?Resolved then translated. Earlier decision selected fixed expiry; under no-clock constraints this is represented as revision lease defaultlease_revs: 2.ShouldResolved: stays in shared-lock scope. Applied to R1.docs/README.mdremain in shared-lock scope or move to PRD-owner-only scope?Should invariant checks be automated in a helper script?Resolved: yes. Captured in M3.
- Turnfile-backed lock + transaction flow is used for one full cross-review phase with no control-plane drift.
- Both agents report lower collision overhead during shared-file edits.
- Maintainer confirms control-plane readability remains high while contention decreases.
- Team confirms scope is minimal and ready for canonical protocol inclusion.