From on-loop
File-level locking with TTL, heartbeat, and stale lock detection for multi-session roadmap coordination
How this skill is triggered — by the user, by Claude, or both
Slash command
/on-loop:roadmap-lockThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill manages file-level locking for multi-session coordination during roadmap execution. Locks prevent multiple sessions from working on conflicting steps simultaneously.
This skill manages file-level locking for multi-session coordination during roadmap execution. Locks prevent multiple sessions from working on conflicting steps simultaneously.
Locks are stored in two places:
roadmap/.state/<feature>.json under locks and within step assigned_session fieldsroadmap/.state/_global.json for cross-feature concerns{
"locks": {
"<step-key>": {
"session_id": "<uuid-v4>",
"session_label": "<human-readable label, e.g. 'Alice laptop'>",
"phase": 1,
"step": 3,
"files": ["path/to/file.py", "path/to/other.py"],
"acquired_at": "<ISO 8601>",
"last_heartbeat": "<ISO 8601>",
"ttl_minutes": 60
}
}
}
roadmap/.state/_global.json:
{
"version": "1.0",
"migration_lock": null,
"active_sessions": {
"<session-id>": {
"session_label": "<human-readable label>",
"feature": "<feature-slug>",
"phase": 1,
"step": 3,
"started_at": "<ISO 8601>",
"last_heartbeat": "<ISO 8601>",
"pid": "<process identifier if available>"
}
}
}
When a new session starts (any command invocation that needs coordination):
python3 -c "import uuid; print(str(uuid.uuid4()))"session_label from the user for human readabilityWhen /on-continue picks up a step:
exclusive: true, verify no other steps in the phase are in-progress
b. If the step has conflicts_with IDs, verify none of those steps are in-progress
c. If any target files overlap with files locked by another session, the lock cannot be acquiredlast_heartbeat
b. If last_heartbeat is more than 10 minutes old, the lock is stale and can be reclaimed
c. Log a warning when reclaiming a stale locklocks in the feature state file
b. Add entry to active_sessions in the global lock file
c. Set last_heartbeat to current timestampWhen a step completes, fails, or /on-pause is invoked:
session_id)locksactive_sessions in the global lock fileWhile a session is actively working on a step:
last_heartbeat in both:
Implementation note: Since Claude Code sessions are not long-running daemons, the heartbeat is written at key milestones during step execution rather than on a timer. Each agent dispatch within /on-continue should update the heartbeat.
When checking lock availability:
last_heartbeat as ISO 8601now - last_heartbeat > 10 minutesUse this Python snippet for comparison:
python3 -c "
from datetime import datetime, timezone, timedelta
last = datetime.fromisoformat('<heartbeat_value>')
now = datetime.now(timezone.utc)
stale = (now - last) > timedelta(minutes=10)
print('stale' if stale else 'active')
"
When a stale lock is detected and a session wants to acquire the step:
[timestamp] WARNING: Reclaiming stale lock on phase <N> step <M> from session <old-session-id> (last heartbeat: <timestamp>)active_sessionsWhen /on-pause is invoked:
session_id)in-progress, leave it as in-progress (another session can reclaim via stale detection, or the same session can resume)
b. Remove the lock entryactive_sessions in the global lock fileTwo steps conflict at the file level if their files arrays have any intersection:
Step A files: ["src/api.py", "src/models.py"]
Step B files: ["src/models.py", "src/utils.py"]
Conflict: "src/models.py" is in both -> cannot run concurrently
Steps can declare conflicts explicitly:
exclusive: true -- This step cannot run while any other step in the same phase is in-progressconflicts_with: [1, 4] -- This step cannot run while steps 1 or 4 are in-progressparallel: true -- This step can run concurrently with other parallel: true steps (unless file conflicts exist)exclusive flag first (most restrictive)conflicts_with listIf roadmap/.state/_global.json does not exist, create it:
{
"version": "1.0",
"migration_lock": null,
"active_sessions": {}
}
The migration_lock field is reserved for future use (e.g., schema migrations that need exclusive access).
npx claudepluginhub joestein/on-loop --plugin on-loopProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.