Problem
The reverse relationship index (_index/relations.json) uses a load-modify-save cycle without file locking. If two agents write relationships to the same app concurrently, one write can be lost.
Current flow in relations.py:
load_index() — read JSON from disk
- Modify in memory
save_index() — atomic write via os.replace
Step 3 is atomic (no torn writes), but the full cycle is not — a concurrent reader at step 1 can get stale data before another writer finishes step 3.
Current Impact
Low. Upjack apps currently run single-agent. The index is also self-healing — rebuild_index reconstructs from entity files, which are the source of truth.
When This Matters
- Multi-agent apps writing to the same namespace concurrently
- High-frequency activity logging from multiple sources
Suggested Approach
fcntl.flock or equivalent advisory lock around the load-modify-save cycle
- Or move to an append-only log that gets compacted periodically
- Keep the auto-rebuild as a fallback regardless
Problem
The reverse relationship index (
_index/relations.json) uses a load-modify-save cycle without file locking. If two agents write relationships to the same app concurrently, one write can be lost.Current flow in
relations.py:load_index()— read JSON from disksave_index()— atomic write viaos.replaceStep 3 is atomic (no torn writes), but the full cycle is not — a concurrent reader at step 1 can get stale data before another writer finishes step 3.
Current Impact
Low. Upjack apps currently run single-agent. The index is also self-healing —
rebuild_indexreconstructs from entity files, which are the source of truth.When This Matters
Suggested Approach
fcntl.flockor equivalent advisory lock around the load-modify-save cycle