Path-scoped write coordination: per-path coordinator lease + per-box zettelkasten locks¶
Angelo › agent-coordinator › Phase 6: Path-scoped write coordination (no thrashing)
Type: Decision · Status: active · Created: 2026-06-25 · Updated: 2026-06-28
Tags: coordinator,write-lease,path-scoped,locking,zettelkasten,box-lock,concurrency,acquire-paths
Replaced the coordinator's global one-implementer-at-a-time write lease with fine-grained path-scoped coordination. Disjoint work runs in parallel; only same-path/same-box writes serialize.
Layer 1 - coordinator path lease (coordinator/graph.py, server.py). Added Task.writes plus pure helpers normalize_write_path/keys_overlap/lease_keys/write_sets_conflict (overlap = path-prefix containment; globs reduced to non-magic prefix; "" = whole-workspace sentinel). Replaced _running_implementer with a process-wide PathLockManager (Condition-backed ledger, non-blocking try_acquire for claims, blocking acquire with timeout for dynamic leases, deadlock-free sorted multi-acquire). claim_task now leases by task.writes: omitted -> whole-workspace (legacy behavior), disjoint paths -> parallel, [] -> dynamic mode. Added acquire_paths/release_paths MCP tools; submit_result auto-releases. writes round-trips through all (de)serialization paths.
Layer 2 - zettelkasten enforced per-box lock (zettelkasten/commit.py, server.py). Discovered review_write_lock is already a generic two-layer (thread + OS advisory) named lock. Added box_write_lock and deadlock-free boxes_write_lock on top. Wrapped every scribe-facing write dispatch (note add/update/link, source create/set_coverage/backfill, graph create, citation , project ) in _zk_write_lock keyed by the box(es)/project(s) it mutates - wrapped at the DISPATCH level (not inside helpers) to keep non-reentrant locks safe. N scribes on N sources extract in parallel; _cross/_citations/same-source writes queue.
Layer 3 - personas + rules. Engineer persona gained a cooperative acquire/release step (dynamic mode only); zettelkasten-extractor persona notes store-enforced locking (no manual leasing). Updated the 'Engineers are sequential' constraint in both .cursor/rules/coordinator.mdc and angelo_cli/data/rules/coordinator.mdc (kept byte-synced per test_cli_data_sync).
Enforcement asymmetry (accepted): ZK is fully enforced (single chokepoint). Generic engineers can only be coordinated cooperatively (the coordinator cannot intercept raw Edit-tool writes), so the cooperative lease is persona-followed, not kernel-enforced.
Tests: TestPathHelpers, TestPathScopedLease (8 cases incl. dynamic acquire/release + auto-release), 4 box_write_lock concurrency tests. Full affected suite green (1225 passed). MCP servers must be restarted in Cursor to pick up the new tools.
Referenced files¶
coordinator/graph.py@6b55ea7coordinator/server.py@6b55ea7coordinator/agents.py@6b55ea7zettelkasten/commit.py@6b55ea7zettelkasten/server.py@6b55ea7- .cursor/agents.yaml@6b55ea7
- .cursor/rules/coordinator.mdc@6b55ea7
angelo_cli/data/rules/coordinator.mdc@6b55ea7tests/test_server.py@6b55ea7tests/test_zettel_review_substrate.py@6b55ea7
Source: memory entry deci-a0778370.