From taskwarrior-plugin
Surface next N unblocked taskwarrior tasks by urgency, skipping lock-contending tasks. Use when planning a parallel-agent wave or choosing tasks for a dispatch slot.
How this skill is triggered — by the user, by Claude, or both
Slash command
/taskwarrior-plugin:task-coordinate optional count (default 3) and lock filteroptional count (default 3) and lock filterThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Next-candidate-agent surfacing for parallel / wave dispatch. Pairs with `agent-patterns-plugin:parallel-agent-dispatch` and `workflow-orchestration-plugin:workflow-wave-dispatch`.
Next-candidate-agent surfacing for parallel / wave dispatch. Pairs with agent-patterns-plugin:parallel-agent-dispatch and workflow-orchestration-plugin:workflow-wave-dispatch.
| Use this skill when... | Use task-status / task-add / task-done instead when... |
|---|---|
| Picking the top-N unblocked tasks for a parallel-agent wave | Producing a full queue audit (pending + blocked + drift) — use task-status |
Filtering candidates that contend on the same exclusive lock (ghidra, migration) | Filing a new task before there is anything to coordinate — use task-add |
Emitting a --wave brief for an orchestrator to fan out | Closing a task that already landed via commit — use task-done |
task --versionfind . -maxdepth 1 -name '.git' -print -quittask _projectsgit rev-parse --show-toplevel writes to stderr in a no-git cwd, and
stderr from a Context backtick aborts the skill before its body runs.
Project resolution is done in the body (Step 1 below) via the Bash tool
where 2>/dev/null and exit-code handling are tolerated.
Parse $ARGUMENTS:
--n=N — number of candidates to surface (default 3)--lock=<resource> — exclude candidates that need the named lock (e.g. ghidra, migration, task-bulk)--wave — format output as a wave brief (orchestrator-ready)--project=<name> — override the auto-detected project filter--all — opt out of project filtering (cross-project wave; rare — usually wrong for dispatch)--include-active — include +ACTIVE (already-claimed) tasks in candidate ranking. Default behaviour excludes them so a wave is never dispatched onto work another agent has already started via /taskwarrior:task-claim.--stale-after=N — threshold (hours) for flagging a +ACTIVE claim as stale in the report. Default 4. Stale claims are reported only — never auto-stopped.Default behaviour is project-scoped. A wave dispatch almost always wants
candidates from a single repo, so cross-project candidates are filtered
out by default. Resolve $PROJECT in this order:
--project=<name> if provided.--all → no project filter (cross-project wave).git rev-parse --show-toplevel 2>/dev/null, run via the
Bash tool (where stderr suppression and non-zero exits are tolerated).Execute this workflow:
Substitute the literal project name into the filter (no $() command
substitution — shell-operator protections will reject it). Use taskwarrior's
native +READY virtual tag, which means pending, unblocked, not waiting, and
either unscheduled or scheduled before now — so it subsumes the old
-BLOCKED clause AND respects scheduled: / wait: dates. Add -ACTIVE to
exclude tasks already claimed via /taskwarrior:task-claim:
task project:myrepo status:pending +READY -ACTIVE export \
| jq 'sort_by(-.urgency) | .[] | {id, description, urgency, tags, bpid, depends, due, scheduled}'
With --include-active, drop the -ACTIVE clause so already-claimed
tasks compete for ranking. With --all, drop the project: clause.
+READY automatically hides wait:-deferred and future-scheduled: tasks,
so a task parked with wait: until a PR merges never appears as a candidate.
Never use task next — exits 1 on empty.
In parallel with Step 1 (these are independent reads), collect the set of currently-claimed tasks for the report:
task project:myrepo status:pending +ACTIVE export \
| jq '.[] | {id, uuid, description, agent, pid, host, branch, worktree, start, urgency}'
Empty array is exit-0 from task export — safe in parallel batches.
Filter the in-flight set for claims older than --stale-after hours:
task project:myrepo +ACTIVE start.before:now-4h export \
| jq '.[] | {id, uuid, agent, host, branch, start}'
Stale claims are surfaced in the report only; task-coordinate never
calls task stop on its own. The orchestrator (or the original claimer)
decides whether to release.
Classify each task by the locks implied by its tags or bpid:
| Tag / ID prefix | Implied lock |
|---|---|
+re on decomp work, tmp/decomp/ in description | ghidra |
+migration, bpid starts with MIG- | migration |
+bulk_task | task-bulk (taskwarrior itself — single-writer) |
Matching bpdoc in shared manifest | manifest |
Drop any candidate that matches the --lock= filter. Two tasks that
would contend on the same lock cannot share a wave — keep the one with
higher urgency, defer the other to the next wave.
Keep the top N by urgency. If ties, prefer:
bpdoc (scope is already written down)entry (older first)Lead the output with the resolved project scope so the orchestrator
knows the wave is single-repo (default) or cross-project (--all):
Project: myrepo (auto-detected from git toplevel)
Default format (compact):
1. #7 WO-012 Implement foo decoder u:14.2
2. #11 WO-013 Add foo CLI subcommand u:12.8
3. #15 WO-014 Document foo format spec u:11.1
With --wave, emit a wave brief:
## Wave N candidates (3 agents, no lock contention)
| # | Task | Scope | Exclusion |
|---|------|-------|-----------|
| A | WO-012 (task #7) | src/codec/foo.c, tests/foo.c | orchestrator-only: CMakeLists.txt |
| B | WO-013 (task #11) | cli/commands/foo.c | orchestrator-only: CMakeLists.txt |
| C | WO-014 (task #15) | docs/format-spec/foo.md | orchestrator-only: docs/blueprint/manifest.json |
Pre-allocated IDs: WO-012, WO-013, WO-014 (see parallel-agent-dispatch §Pre-Allocated Blueprint IDs).
If the rank step dropped any lock-contending candidates, report them as
deferred-to-next-wave with the lock name — the orchestrator decides
whether to pre-dump via exclusive-lock-dispatch or serialise.
Always emit two trailing sections so the orchestrator sees the full state of the project queue, not just the dispatchable subset:
## In flight (claimed)
| Task | UUID | Agent | Branch | Host | Started |
|------|------|-------|--------|------|---------|
| #4 (WO-008) | a1b2c3d4 | claude-a1b2c3d4 | feature/parser | host-1 | 2h ago |
| #9 (WO-011) | 9f8e7d6c | claude-9f8e7d6c | feature/api | host-2 | 30m ago |
## Stale claims (>4h)
| Task | UUID | Agent | Started | Action |
|------|------|-------|---------|--------|
| #2 (WO-005) | 44556677 | claude-44556677 | 6h ago | Investigate; release with `/taskwarrior:task-release 2` (or the UUID) if abandoned |
Empty sections render as "(none)". Never auto-stop a stale claim —
report only, per the v1 design. UUID is convenience, not the safety
mechanism (.claude/rules/task-id-stability.md).
| Context | Command |
|---|---|
| Project ready + unclaimed | task project:myrepo status:pending +READY -ACTIVE export | jq 'sort_by(-.urgency)' |
| Include claimed (rare) | drop -ACTIVE clause |
| Overdue candidates | task project:myrepo status:pending +OVERDUE export | jq 'sort_by(-.urgency)' |
| In-flight snapshot | task project:myrepo +ACTIVE export | jq '.[] | {id, agent, branch, start}' |
| Stale claims | task project:myrepo +ACTIVE start.before:now-4h export | jq |
Cross-project (--all) | task status:pending +READY -ACTIVE export | jq 'sort_by(-.urgency)' |
| Same-lock siblings | Filter on tags / bpid prefix locally, not via task filter |
| Wave brief | --wave flag emits table with exclusion column |
| Skip failing-filter variants | Never task next, always export | jq |
| Flag | Default | Purpose |
|---|---|---|
--n=3 | 3 | How many candidates |
--lock=ghidra | unset | Drop ghidra-contending tasks |
--wave | off | Emit wave brief format |
--project=<name> | repo basename | Override the project filter |
--all | off | Disable project filter (cross-project wave) |
--include-active | off | Include +ACTIVE (claimed) tasks in candidate ranking |
--stale-after=N | 4 | Hours before a +ACTIVE claim is flagged stale in the report |
/taskwarrior:task-claim — the skill agents call after picking a candidate (sets +ACTIVE, which this skill respects)/taskwarrior:task-release — release a stale claim surfaced by this skill/taskwarrior:task-status — full queue auditagent-patterns-plugin:parallel-agent-dispatch — the dispatch contract these candidates feedagent-patterns-plugin:exclusive-lock-dispatch — when to pre-dump instead of serialiseworkflow-orchestration-plugin:workflow-wave-dispatch — wave scheduling that consumes the brief.claude/rules/parallel-safe-queries.md — export | jq idiom.claude/rules/task-id-stability.md — UUID column is convenience, not the mechanismnpx claudepluginhub laurigates/claude-plugins --plugin taskwarrior-pluginRead-only taskwarrior queue report — pending, blocked, ready tasks and drift vs linked PRs. Use when auditing queue health, orienting before a wave, or for standup summaries.
Graph-aware next task recommendation with SA context enrichment. Reads Task/Wave from Neo4j, enriches with UC entity/form names.Use when: next task with graph, what to work on, or the user says "/nacl:tl-next".
Executes eligible tasks from session task list, syncs against codebase/PR state to surface stales, and generates handovers. Use /task-run [--all] [--sync [--dry-run]] [--handover [query]].