agent-patterns-plugin/skills/exclusive-lock-dispatch/SKILL.md
Pre-dump-then-dispatch for tools holding an exclusive lock (Ghidra, migrations, single-writer caches). Use when fanning out parallel agents needing a non-concurrent resource.
npx skillsauth add laurigates/claude-plugins exclusive-lock-dispatchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The dispatch-time pattern for tools that hold an exclusive lock during execution. Running such a tool from multiple parallel agents is a guaranteed failure; running the same tool's outputs through many parallel agents is the right shape.
| Use this skill when… | Use parallel-agent-dispatch alone when… |
|----------------------|-------------------------------------------|
| Two or more candidate agents would invoke the same lock-holding tool | No candidate agent touches a locked resource |
| A prior wave emitted lock-contention errors | Agents only read pre-computed artefacts |
| You are debating "serialise the agent or pre-dump the artefacts?" | File scopes are disjoint and lock-free |
| The tool in question is slow (decompilation, migration, compile) so re-running per agent would burn minutes | The lock holder is cheap enough to serialise without pre-dump |
| Tool / Resource | Lock Behaviour | Typical Symptom |
|-----------------|---------------|-----------------|
| Ghidra project (.gpr) | Single writer; second invocation fails | Project is locked by another instance |
| Database migration lock | Single writer per database | Migration tool blocks or errors |
| Git index on shared checkout (.git/index.lock) | Single writer per working tree | index.lock exists / cannot git add |
| Taskwarrior bulk modify (task modify, task done ranges) | Effectively single-writer for the task store | Sporadic "task database is locked" or lost edits |
| Single-writer build caches (ccache, cargo target/, Bazel action cache) | First writer serialises others | Spurious build failures or cache corruption |
| Decompiler output caches | Re-analysis on every access | Minutes-per-agent rerun when artefacts could be shared |
Wave plan:
Agent A: ghidra -process BIN --script ExtractStrings.java
Agent B: ghidra -process BIN --script ExtractXrefs.java
Agent C: ghidra -process BIN --script ExtractStructs.java
Dispatched in parallel.
Second invocation refuses to open the project. The orchestrator receives two "failed" returns and, without this skill's discipline, dispatches more agents to "retry" — multiplying the lock contention.
Run the locked tool exactly once (or once per distinct artefact kind), writing everything downstream agents will need into gitignored scratch. Keep the outputs under a stable path that the brief can reference:
tmp/decomp/strings.txt
tmp/decomp/xrefs.json
tmp/decomp/structs.json
tmp/ghidra/analysis.log
The pre-dump agent runs alone in its wave. Its return contract includes the artefact paths as "produced" so downstream waves can cite them.
Parallel agents in the next wave take the pre-computed artefacts as input and produce their implementation slabs from those. No lock-holder invocations, no re-analysis, no contention.
Briefs must reference artefacts by path:
"Input artefacts:
tmp/decomp/strings.txt,tmp/decomp/xrefs.json. Treat as read-only. Do not re-run Ghidra."
The orchestrator never places two lock-contenders in the same wave.
workflow-wave-dispatch handles the scheduling; this skill is the
pre-work that makes wide parallelism possible afterwards.
| Situation | Decision | |-----------|----------| | N ≥ 2 candidate agents would each need a fresh analysis of the same source | Pre-dump: one serialised run, then fan out | | Exactly one agent needs the lock and no siblings do | Dispatch directly: the lone agent serialises itself | | Lock holder is fast (< 10s) and agents need fresh state | Dispatch serially: skip pre-dump, run agents one at a time | | Lock holder is slow and agents need only a stable snapshot | Pre-dump: amortises the cost across the fan-out |
The pre-dump cost is paid once. Serialising N agents pays the lock cost N times and removes any parallelism benefit.
Ghidra is the most common pre-dump target. The 12.x release changed scripting:
| Concern | Current-as-of-2026 Answer |
|---------|---------------------------|
| Scripting language | .java post-scripts (Jython removed in 12.x) |
| First-time vs re-run | -import on first run; -process once the binary is in the project |
| Skip analyzers on re-run | -noanalysis |
| Headless wrapper | analyzeHeadless <project_dir> <project_name> |
| Output destination | Post-script writes to stdout or to a file under tmp/ |
A typical pre-dump recipe:
# First run: import and analyse once
analyzeHeadless tmp/ghidra/ myproj -import path/to/bin \
-postScript ExtractEverything.java tmp/decomp/
# Later runs: re-use analysis
analyzeHeadless tmp/ghidra/ myproj -process bin -noanalysis \
-postScript RefreshStrings.java tmp/decomp/
The ~/.task/ store is single-writer in practice. Dispatching five
agents to each task modify different filters produces sporadic
"database is locked" errors and, worse, silently lost edits when one
agent's write races another's.
The rule is the same: one orchestrator-owned agent (or the orchestrator
itself) performs the bulk mutation, derived tasks the parallel siblings
need are emitted to gitignored scratch (tmp/tasks.json), and the
parallel wave reads from scratch.
tmp/| Mistake | Correct Approach |
|---------|-----------------|
| Dispatching N agents that each run the locked tool | Pre-dump once, fan out on artefacts |
| Retrying the locked agent on failure | Diagnose the lock, then either serialise or pre-dump |
| Committing tmp/decomp/ or tmp/ghidra/ | .gitignore the scratch directory |
| Briefing "and run Ghidra again to double-check" | Once the artefacts exist, treat them as authoritative |
parallel-agent-dispatch — overall dispatch contract; §Wave Splits cites this skillworkflow-wave-dispatch — wave scheduling between lock-holder and parallel waves.claude/rules/parallel-safe-queries.md — commands that exit 1 on empty, a different form of parallel foot-gunEvidence: six-wave renderer landing shipped with zero lock-contention retries after adopting pre-dump for the decompiler and the task queue. Before this discipline, ad-hoc parallel dispatches frequently consumed an entire wave recovering from lock errors.
tools
Scaffold a new ComfyUI custom-node repo (pyproject, CI, release-please, vitest+pytest, JS extension skeleton) in the picker/gesture vein. Use when bootstrapping or init-ing a comfyui node pack.
tools
Orchestrate a ComfyUI node pack from idea to registry: scaffold, create + seed the repo, open the gitops adoption PR. Use when releasing or spinning up a new comfyui node pack.
testing
macOS EndpointSecurity/EDR high CPU & battery drain. Use when Kandji ESF / XProtect pegs a core; trace the exec storm via powermetrics + eslogger.
development
odiff pixel-by-pixel image diffing. Use when comparing screenshots, detecting visual regressions, diffing before/after PNGs, asserting golden images.