Skip to content

fix(locks): free every root on release --all - #199

Merged
AbysmalBiscuit merged 1 commit into
mainfrom
197-fix-locks-release-all-frees-every-root
Sep 27, 2026
Merged

AbysmalBiscuit merged 1 commit into
mainfrom
197-fix-locks-release-all-frees-every-root

Conversation

@AbysmalBiscuit

@AbysmalBiscuit AbysmalBiscuit commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

TL;DR (human written)


Closes #197


Agent summary

lockm release --all only freed the session's locks in the checkout it ran from. The write hook claims in whichever checkout a write lands in, so a session that wrote into a second worktree or a scratch directory kept those claims until the TTL ran out or the session ended. The using-devkit skill calls --all "drop everything you hold".

release --all now frees every lock held by exactly that holder, in every root. Holder ids are globally unique, so the root filter protected nothing.

  • Sub-agent rows (holder/agent) stay, as references/locks.md already documented. They have their own cleanup in SubagentStop, and a top-level --all taking them would pull locks out from under a sub-agent that is still running.
  • The daemon's ReleaseAll request keeps its root field for wire compatibility, and the lock proto stays at 4. The daemon ignores the field. An older daemon still parses the request and releases in the caller's root, the old behavior. A proto bump would have failed the handshake, and the fallback file store refuses every lock write while a daemon holds the registry, so edits in enforced checkouts would have been denied until the daemon restarted. release_all_keeps_its_wire_shape pins the serialized shape.
  • MCP locks.release with all: true gets the same scope, since it calls the same function.
  • release --all -h, SKILL.md, references/locks.md and the MCP field description now describe the same scope.

release_all_frees_the_holder_in_every_root drives the real lockm binary across two git checkouts with alice, alice/agent and bob holding locks in each. Before the fix it released 1 lock instead of 2. resolved_fns_roundtrip_via_flock_path writes to the real registry, so its fixed holder-a id became a per-process id: a cross-root release could otherwise free another concurrent run's rows.

Not checked locally: macOS and Windows. Nothing here is platform-specific.


🤖 Generated with Claude Opus 5.5 via Claude Code

lockm release --all only freed the holder's rows under the root of
the checkout it ran from. The write hook claims in whichever checkout
a write lands in, so a session that wrote into a second worktree or a
scratch directory kept those claims until the TTL or session end,
though the using-devkit skill promised "drop everything you hold".

Release matches on the exact holder alone. Holder ids are globally
unique, so the root filter bought nothing. Sub-agent rows
(holder/agent) still stay for SubagentStop, as locks.md already
documented. The daemon ReleaseAll request keeps its root field for
wire compatibility: the daemon ignores it, and an older daemon still
parses the request and releases in the caller's root, instead of
failing the handshake and refusing every lock write until it
restarts. MCP locks.release with all=true gets the same scope through
the shared function.

Closes #197

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@AbysmalBiscuit
AbysmalBiscuit force-pushed the 197-fix-locks-release-all-frees-every-root branch from 4f65041 to 8ed351b Compare September 27, 2026 20:03
@AbysmalBiscuit
AbysmalBiscuit merged commit d55ba01 into main Sep 27, 2026
13 checks passed
@AbysmalBiscuit
AbysmalBiscuit deleted the 197-fix-locks-release-all-frees-every-root branch September 27, 2026 20:13
AbysmalBiscuit added a commit that referenced this pull request Sep 27, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.14.7](v0.14.6...v0.14.7)
(2026-09-27)


### Features

* **brief:** add a rules section
([#160](#160))
([7ba41e2](7ba41e2))
* **brief:** list tasks by app and trim the brief
([#162](#162))
([d991929](d991929))
* **command:** model permission changes
([#174](#174))
([4aea742](4aea742))
* **config:** describe task args and variables
([#159](#159))
([34e0076](34e0076))
* **docm:** treeless clones and per-library excludes
([#157](#157))
([a4f4410](a4f4410))
* **forge:** support GitLab and Forgejo alongside GitHub
([#183](#183))
([1926908](1926908))
* **harness:** claim bounded shell write sets
([#158](#158))
([a72acf1](a72acf1))
* **hook:** parse Cursor and Antigravity payloads with pabal 0.2
([#191](#191))
([00e2918](00e2918))
* **hooks:** add before_worktree_remove
([#140](#140))
([1ea3aed](1ea3aed))
* **issue:** add dashboard chart aggregation modes
([#144](#144))
([61ad36a](61ad36a))
* **issue:** label the y-axis of dashboard charts
([#143](#143))
([99e7b29](99e7b29))
* **issues:** create issues from enforced templates
([#185](#185))
([3a38874](3a38874))
* **issue:** take the summary from the tracker
([#138](#138))
([30425fb](30425fb))
* **rules:** add rules add, edit and remove
([#150](#150))
([7052dd4](7052dd4))
* **rules:** honor repo-rules-agent.toml in query
([#151](#151))
([e7a1d1f](e7a1d1f))
* **template:** render templates on demand
([#165](#165))
([2da3c36](2da3c36))
* **templates:** add variable descriptions
([#152](#152))
([918f594](918f594))


### Bug Fixes

* **command:** end the fresh-path exemption on placement
([#125](#125))
([40ae328](40ae328))
* **common:** keep live blocks from climbing over output
([#141](#141))
([2e2b919](2e2b919))
* **git:** fail fast when ssh needs a prompt
([#142](#142))
([8fe7ae3](8fe7ae3))
* **guard:** note each unresolved command once
([#200](#200))
([2bcd2fa](2bcd2fa))
* **guard:** redirect only commands a task covers
([#198](#198))
([f6c0488](f6c0488))
* **hooks:** keep enforcement on past a broken layer
([#190](#190))
([8846a35](8846a35))
* **issue:** allow setup --slug without an issue id
([#127](#127))
([7c28ba7](7c28ba7))
* **issue:** dashboard spinners, x labels and status colors
([#149](#149))
([b35e2ed](b35e2ed))
* **issue:** hold worktrees past their merged PR
([#189](#189))
([a27a28b](a27a28b))
* **issue:** make status, info, end and MCP agree
([#193](#193))
([cd9b46a](cd9b46a))
* **issue:** report ambiguous branch PRs in review finish
([#192](#192))
([ff2cf62](ff2cf62))
* **locks:** free every root on release --all
([#199](#199))
([d55ba01](d55ba01))
* **tasks:** refuse a blank required arg
([#173](#173))
([d1b32b3](d1b32b3))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(locks): release --all frees every root

1 participant