Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add tmj-90/gaffer --skill concurrency-and-asyncgit clone --depth 1 https://github.com/tmj-90/gafferWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/tmj-90/gaffer/concurrency-and-async)<a href="https://agentmods.dev/skills/tmj-90/gaffer/concurrency-and-async"><img src="https://agentmods.dev/badge/skills/tmj-90/gaffer/concurrency-and-async/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/tmj-90/gaffer/concurrency-and-async"><img src="https://agentmods.dev/badge/skills/tmj-90/gaffer/concurrency-and-async.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00108 | $0.02151 |
| Opus 5.5 | $0.00043 | $0.00860 |
| Sonnet 5.5 | $0.00022 | $0.00430 |
| Haiku 4.5 | $0.00011 | $0.00215 |
Grade A, and why
concurrency-and-async scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 16d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 130 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Write concurrent code that is correct under interleaving
Concurrency bugs pass every sequential test. Live builds of the same app twice shipped the same class past review: fixed temp-file names colliding under parallel requests (HTTP 500), unsynchronised read-modify-write losing updates, and a time-only stale-lock lease that dropped an acknowledged write when the holder was paused past the threshold. Assume that any code with a shared file, row, counter or lock has one of these until a test that forces the schedule proves otherwise.
Steps
- Inventory shared state and writers. For every file, row, counter, cache entry or
lock file the change touches, list who can write it: concurrent requests in one async
process (every
awaitis a yield point), threads, other worker processes or instances, and a restarted process after a crash. Callsearch_lorefor the repo's lock helper, worker model and transaction rules. Each item must end up immutable, single-owner (one queue/actor/goroutine does all writes), or guarded. - Pick the guard by scope. In one process: a mutex or per-key async lock, or a
single-writer queue. Across processes on one host: an OS lock the kernel releases on
death (
flock/fcntl,LockFileEx). Across hosts or on database rows: the database (UPDATE … SET n = n + 1,SELECT … FOR UPDATE, a unique constraint, a version column,pg_advisory_xact_lock). An in-memory flag guards nothing once there are two processes. - Serialise every read-modify-write. Read → compute → write with no guard loses
updates. Use one atomic statement; or compare-and-swap
(
UPDATE t SET v = v + 1, data = ? WHERE id = ? AND v = ?, check the affected row count, retry a bounded number of times, then 409); or hold one lock across the whole read, modify and write. A lock around only the write does not help. Check-then-act across anawait(if (!exists) await create()) is the same bug. - Write files atomically. Create the temp file in the same directory with a
unique name (
mkstemp,os.CreateTemp,O_CREAT|O_EXCL, or pid + random suffix — never a fixeddata.json.tmpor a timestamp), write,fsyncit when the data must survive power loss,renameover the target (os.replacein Python), thenfsyncthe directory for a durable rename; delete the temp on failure. Use a library such aswrite-file-atomic(Node) orrenameio(Go) only if it is already a dependency; never install one. Rename gives readers old-or-new, never a torn file — it does not serialise writers, so step 3 still applies. Acknowledge (2xx, return success) only after the rename, and after the fsyncs when durability is the contract. - Make cross-process locks safe against pauses. A process can stop for seconds
without dying: GC,
SIGSTOP, VM suspend, swap, a debugger. A lock declared stale because of age alone is then stolen while its holder still believes it owns it; the holder resumes and overwrites the new owner's acknowledged write. In order of preference:- a kernel-held lock (
flock/fcntl) released when the owner process dies and never because time passed; or a Postgres advisory lock taken on the same connection or transaction that performs every guarded write (pg_advisory_xact_lock). Postgres releases it whenever the session ends (idle timeout, dropped connection, pooler), so it protects only writes made through that session — never a file or another store; - an owner-liveness check: the lock records pid, host and process start time or a
nonce, and is broken only when that owner is provably gone — same host, and either
kill(pid, 0)fails with ESRCH or the process now running under that pid has a different start time (pid reuse).EPERMonly means some process holds that pid: compare its start time, and never treatEPERMalone as gone. Age may trigger the check, never decide it; - a fencing token when a time lease is unavoidable (distributed lock, job lease):
each grant returns a monotonically increasing number, every write carries it, and
the resource rejects a token lower than the highest it has accepted.
"Re-check I still hold the lock, then write" is not a substitute (unless the check
takes a row lock held until the write commits, as in the
scheduled-jobsskill); the pause can land between check and write.
- a kernel-held lock (
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 16d ago Changed · +63 lines · +21 tokens per session 9ecde85367e7
- 19d ago First seen · 67 lines · 87 tokens per session scan A 411e39e47749
concurrency-and-async is a skill published in the GitHub repository tmj-90/gaffer (2 stars, last pushed 17d ago), licensed Apache-2.0. It adds 108 tokens to every session and 2,151 once invoked, about $0.0004 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-28.
Other skills, from other repositories
issue-debugging
Systematic methodology for issue debugging including root cause analysis, impact mapping, tiered validation plans, and confidence assessment. Use when analyzing bugs, fixing issues, or validating fixes.
fix-bug
Run the Fix Validation pipeline to investigate, fix, and validate a bug. Ensures deterministic pipeline execution with IssueAnalyzer, FixWriter, TestWriter (conditional), TestAudit (conditional), and FixValidator stages.
pact-bug
Log a bug investigation using PACT's structured bug tracker.
browser-edge-cases
SOP for debugging browser automation failures on complex websites. Use when browser tools fail on specific sites like LinkedIn, Twitter/X, SPAs, or sites with Shadow DOM.
triage-issue
Analyze a GitHub issue, verify claims against the codebase, and close invalid issues with a technical response.
hive.error-recovery
Follow a structured recovery decision tree when tool calls fail instead of blindly retrying or giving up.