/session-conflicts
Check for file lock, project, task, and CWD conflicts across active LLM sessions using the Inter-Session Message Bus (messaging.db) to prevent silent overwrites and coordinate multi-session work.
Purpose
Queries the file_locks table and session_messages (operator alerts) in messaging.db (ADR-160, ADR-173) to detect file locks, project overlaps, task claim conflicts, and CWD collisions. Uses advisory file locks with automatic stale lock cleanup, plus structured conflict detection from ADR-173.
Usage
# Check specific file
/session-conflicts path/to/file.py
# Check multiple files
/session-conflicts file1.py file2.md file3.json
# Show all active file locks
/session-conflicts --all
# Show all conflict types (file, project, task, cwd) (ADR-173)
/session-conflicts --full
# Show operator alerts only (ADR-173)
/session-conflicts --alerts
# Try to acquire a lock
/session-conflicts --lock path/to/file.py
Arguments
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
file | string[] | No | - | File path(s) to check for lock conflicts |
--all | flag | No | false | Show all file locks across all sessions |
--full | flag | No | false | Show all conflict types: file locks + project + task + CWD (ADR-173) |
--alerts | flag | No | false | Show operator alerts from conflict detection (ADR-173) |
--lock | flag | No | false | Attempt to acquire lock (not just check) |
--unlock | flag | No | false | Release lock on specified file(s) |
System Prompt
When the user invokes /session-conflicts:
-
Connect to message bus:
from scripts.core.session_message_bus import get_session_message_bus
bus = get_session_message_bus() -
Check file locks:
import os
current_session = f"claude-{os.getpid()}"
locks = bus.get_file_locks()
conflicts = {}
for file_path in files:
for lock in locks:
if lock.file_path == str(file_path) and lock.session_id != current_session:
conflicts[str(file_path)] = lock -
Check structured conflicts (ADR-173) — for
--fullor--alerts:# Get operator alerts (project/task/cwd/file conflicts)
alerts = bus.get_operator_alerts(unread_only=False, limit=50)
# Group by type
project_conflicts = [a for a in alerts if a.message_type == "project_conflict"]
task_conflicts = [a for a in alerts if a.message_type == "task_conflict"]
cwd_overlaps = [a for a in alerts if a.message_type == "cwd_overlap"]
file_conflicts = [a for a in alerts if a.message_type == "file_conflict"] -
Optionally acquire locks:
if args.lock:
for file_path in files:
acquired = bus.lock_file(str(file_path), session_id=current_session)
if not acquired:
print(f"CONFLICT: {file_path} locked by another session") -
Format output:
- If file conflicts found: Show warning with lock holder details
- If no file conflicts: Success message
- If --all: Show all active file locks
- If --full: Show all conflict types (file + project + task + CWD)
- If --alerts: Show operator alerts grouped by type with priority labels
Output Examples
No Conflicts
No lock conflicts detected.
Checked files:
- src/main.py
- src/utils.py
All files are safe to edit.
File Lock Conflict
CONFLICT: src/main.py is locked
Lock holder:
Session: codex-67890
Vendor: codex (o3)
Project: PILOT
Task: J.15.6
PID: 67890
RECOMMENDATION: Coordinate with the codex session before editing.
Run /session-status for full session details.
--all Output
Active File Locks
==================================================
session_message_bus.py -> claude-29583 (claude, opus-4.6)
paths.py -> claude-29583 (claude, opus-4.6)
context_extractor.py -> codex-41200 (codex, o3)
Total: 3 locks across 2 sessions
--full Output (ADR-173)
All Conflicts — File Locks + Project + Task + CWD
==================================================
FILE LOCKS (3):
session_message_bus.py -> claude-29583 (claude, opus-4.6)
paths.py -> claude-29583 (claude, opus-4.6)
context_extractor.py -> codex-41200 (codex, o3)
PROJECT CONFLICTS (1):
[CRITICAL] PILOT — shared by claude-29583, codex-41200
Recommendation: Ensure non-overlapping task boundaries
TASK CONFLICTS (0):
No task conflicts detected.
CWD OVERLAPS (1):
[HIGH] /Users/halcasteel/PROJECTS/coditect-rollout-master
claude-29583, codex-41200
Recommendation: One session should work in a subdirectory
Total: 3 file locks, 1 project conflict, 0 task conflicts, 1 CWD overlap
--alerts Output (ADR-173)
Operator Alerts
==================================================
[CRITICAL] project_conflict — 2026-02-11T00:31:37Z
Sessions: claude-29583, codex-41200
Project: PILOT
Status: pending (unread)
[HIGH] cwd_overlap — 2026-02-11T00:31:37Z
Sessions: claude-29583, codex-41200
CWD: /Users/halcasteel/PROJECTS/coditect-rollout-master
Status: pending (unread)
Total: 2 alerts (2 unread)
Lock Acquired
Lock acquired: src/main.py -> claude-29583
Other sessions will see this file as locked.
Run /session-conflicts --unlock src/main.py to release.
Lock Semantics
| Behavior | Description |
|---|---|
| Advisory | Locks are advisory - they warn but don't prevent writes |
| Session-scoped | Locks auto-released when session unregisters |
| Stale cleanup | Locks from dead sessions auto-released |
| Re-entrant | Same session can re-lock a file it already holds |
| Conflict | Different session cannot lock an already-locked file |
When to Use
Use this command when:
- About to edit a file that other sessions might be working on
- Need to claim exclusive access to a file
- Debugging why another session's edits were overwritten
- Coordinating multi-LLM work on shared files
Common Workflows
Workflow 1: Lock Before Edit
# 1. Lock the file
/session-conflicts --lock src/critical-file.py
# 2. Edit safely (other sessions see the lock)
# ... make changes ...
# 3. Release when done
/session-conflicts --unlock src/critical-file.py
Workflow 2: Check Before Starting
# 1. Check all locks
/session-conflicts --all
# 2. If target file is free, proceed
# 3. If target file is locked, coordinate with lock holder
Integration
File locks integrate with the full message bus:
- Registration:
bus.register_session()enables lock ownership - Lock/Unlock:
bus.lock_file()/bus.unlock_file() - Stale cleanup: Expired sessions have locks auto-released
- Unregister:
bus.unregister_session()releases all locks
Error Handling
| Error | Cause | Solution |
|---|---|---|
| "Not registered" | Session not in registry | Run /session-register first |
| "Database not found" | messaging.db missing | Run CODITECT-CORE-INITIAL-SETUP.py |
| "Lock held" | Another active session holds lock | Coordinate with lock holder |
Related Commands
| Command | Purpose |
|---|---|
/session-register | Register session (required for locking) |
/session-status | Show all sessions and their locks |
/session-rescue | Recover hung sessions (releases their locks) |
Architecture
- Database:
~/.coditect-data/context-storage/messaging.db - Tables:
file_locks,session_messages(operator_alert channel) - Python API:
scripts/core/session_message_bus.py - ADR: ADR-160, ADR-173
Version: 3.0.0 Created: 2026-02-07 Updated: 2026-02-11 Author: Claude Opus 4.6 Track: H (Framework Autonomy) Task: H.13.9
Changelog:
- v3.0.0 - ADR-173 v2:
--fullshows all conflict types (file/project/task/CWD),--alertsshows operator alerts, structured conflict detection viaget_operator_alerts() - v2.0.0 - Inter-Session Message Bus integration (ADR-160), file lock checking
- v1.0.0 - Basic file conflict detection