Skip to main content

/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

ArgumentTypeRequiredDefaultDescription
filestring[]No-File path(s) to check for lock conflicts
--allflagNofalseShow all file locks across all sessions
--fullflagNofalseShow all conflict types: file locks + project + task + CWD (ADR-173)
--alertsflagNofalseShow operator alerts from conflict detection (ADR-173)
--lockflagNofalseAttempt to acquire lock (not just check)
--unlockflagNofalseRelease lock on specified file(s)

System Prompt

When the user invokes /session-conflicts:

  1. Connect to message bus:

    from scripts.core.session_message_bus import get_session_message_bus
    bus = get_session_message_bus()
  2. 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
  3. Check structured conflicts (ADR-173) — for --full or --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"]
  4. 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")
  5. 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

BehaviorDescription
AdvisoryLocks are advisory - they warn but don't prevent writes
Session-scopedLocks auto-released when session unregisters
Stale cleanupLocks from dead sessions auto-released
Re-entrantSame session can re-lock a file it already holds
ConflictDifferent 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

ErrorCauseSolution
"Not registered"Session not in registryRun /session-register first
"Database not found"messaging.db missingRun CODITECT-CORE-INITIAL-SETUP.py
"Lock held"Another active session holds lockCoordinate with lock holder
CommandPurpose
/session-registerRegister session (required for locking)
/session-statusShow all sessions and their locks
/session-rescueRecover 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: --full shows all conflict types (file/project/task/CWD), --alerts shows operator alerts, structured conflict detection via get_operator_alerts()
  • v2.0.0 - Inter-Session Message Bus integration (ADR-160), file lock checking
  • v1.0.0 - Basic file conflict detection