<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rulesets/claude-templates/.ai/scripts/agent-lock, branch main</title>
<subtitle>Claude Code skills, rules, and language bundles
</subtitle>
<id>https://git.cjennings.net/rulesets/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/rulesets/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/'/>
<updated>2026-07-19T09:50:21+00:00</updated>
<entry>
<title>feat(sentry): add agent-lock mkdir-atomic advisory lock helper</title>
<updated>2026-07-19T09:50:21+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-19T09:50:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=a8b6cf4fba4420d8cc657604473259b5242d8c37'/>
<id>urn:sha1:a8b6cf4fba4420d8cc657604473259b5242d8c37</id>
<content type='text'>
Phase 1 of the sentry supervisor workflow. sentry needs two locks: a single-runner lock so overlapping /loop fires don't stack, and a roam-write lock so agent edits to the shared roam tree serialize. flock can't serve either, because every Bash call an agent makes is its own short-lived shell, so an flock dies with the call that took it.

agent-lock persists the lock on disk between calls. An atomic mkdir is the acquire. A metadata file inside records pid, host, ISO timestamp, and TTL. Staleness is age-based on the meta mtime, so a crashed holder's lock expires instead of wedging every later acquire, and every reclaim surfaces a note rather than clearing silently. refresh re-touches the mtime as a heartbeat, release is idempotent, status reports free/held/stale, path prints the resolved dir. Locks live under XDG_RUNTIME_DIR/agent-locks (tmpfs: host-local, out of every repo, cleared on reboot), with a ~/.cache fallback where no runtime dir exists.

Reclaim claims the stale dir with an atomic rename before removing it, so two acquirers that both see a lock stale can't both win. A plain remove-then-mkdir would let the loser delete the winner's fresh lock and double-acquire, defeating the roam-write lock's purpose.

Nothing calls it yet. 18 bats tests cover fresh win, contention, release, stale reclaim, heartbeat, path resolution, and usage errors.
</content>
</entry>
</feed>
