skills/mav-block-propagation/SKILL.md
Idempotent, resumable propagation of a `blocked-by:#N` block from an ejected story to every transitive downstream story in the epic DAG. Triggered when agent-code-reviewer ejects a PR for human handling.
npx skillsauth add thermiteau/maverick mav-block-propagationInstall 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.
Depends on: mav-durability-on-gh
When an agent-code-reviewer ejects a PR for human handling, every downstream story that depended on it is now transitively broken. This skill defines how to label them, cancel their in-flight work, and resume cleanly if the propagation itself is interrupted mid-flight.
Without propagation, downstream stories happily continue branching off and
stacking on top of a broken base. They produce PRs that either cannot merge
(build fails) or merge into a broken tree. The blocked-by:#N label is the
mechanism that stops every instance from trying.
Block propagation runs in three steps, and each step is durable on GitHub so the walk can resume after a crash:
digraph bprop {
"Story N ejected" [shape=box];
"Write maverick-bprop marker on epic" [shape=box];
"Walk DAG — apply blocked-by:#N to every descendant" [shape=box];
"Clear maverick-bprop marker" [shape=box];
"Story N ejected" -> "Write maverick-bprop marker on epic";
"Write maverick-bprop marker on epic" -> "Walk DAG — apply blocked-by:#N to every descendant";
"Walk DAG — apply blocked-by:#N to every descendant" -> "Clear maverick-bprop marker";
}
Before labelling any issue, write a maverick-bprop marker on the epic
issue naming the ejected story and every descendant that must be blocked.
The marker says: a block walk is in progress; if you find this, resume it.
Payload shape:
{
"ejected": "142",
"descendants": ["150", "160", "161"],
"labelled": [],
"started_at": "2026-04-23T10:20:00Z"
}
For each descendant, in any order:
gh issue view <id> --json labels.blocked-by:#<ejected> is already present, skip (idempotent re-run).gh issue edit <id> --add-label "blocked-by:#<ejected>"maverick-state on the epic: set that story to blocked.labelled in the maverick-bprop payload.The protocol is idempotent: every step re-checks state before acting, so an interrupted walk can be re-entered from Step 1 and will resume where it left off without re-labelling or re-commenting.
Once every descendant in the payload is in labelled, delete the
maverick-bprop comment. The epic issue is now quiescent.
A block is useless if a subagent is already deep into a now-blocked story — it will push a PR against a broken base. As part of the walk:
.maverick/worktrees/ for any worktree whose branch name refers to
a story now in the blocked set.mav-multi-instance-coordination), do not push its work.Do not attempt to salvage in-progress work. The base is broken; the work cannot be preserved usefully.
Three places must re-check the block state at entry so a late-arriving block unblocks cleanly:
| Location | Check | Behaviour on block |
| --- | --- | --- |
| Cold-start target resolution | Target has blocked-by:#N? | Abort cleanly — report to user |
| Wave selection | Story has blocked-by:#N? | Exclude from wave |
| Per-story re-verify (just before coding) | Story gained blocked-by:#N since wave start? | Abort story; release claim |
The per-story re-verify catches the race where a block is applied after a wave started but before every subagent has picked up its story.
A story is "unblocked" when any of these is true:
blocked-by:#N label has been removed manually by a human.Maverick itself does not auto-unblock. Unblocking requires a human
decision because the original ejection was explicitly delegated to a
human. Wave selection re-reads the blocked-by label each time, so a
human-removed label will let the story run on the next wave-selection pass.
blocked-by:#N on your target,
abort and report — don't modify the issue, don't push, don't claim.blocked-by:#N label from inside the workflow. Only a
human may remove it. Maverick only applies and reads.development
--- name: do-test description: Write or update tests for a code change. Operates in two modes: `unit` (module-scoped, fast, deterministic) and `integration` (crosses module / service / database boundaries). Intended to be invoked once per testable change from inside a do-issue-* or do-epic phase. Mode is required. argument-hint: mode: unit or integration user-invocable: true disable-model-invocation: false --- **Depends on:** mav-bp-unit-testing, mav-bp-integration-testing, mav-local-verificati
development
Implement a focused code change. Use this skill as the wrapper for any implementation work so the Maverick workflow report captures what was done and so the agent applies the project's coding standards before editing. Intended to be invoked once per task from inside a do-issue-* or do-epic phase, not standalone.
testing
How to stack a PR on top of an unmerged sibling branch, and how to retarget it to the repo's default branch once the sibling merges. Prevents orphan-merge incidents when a dependent story is ready before its parent.
development
Claim, lease, heartbeat, and release protocols for when multiple Claude Code instances may act on the same issue or epic concurrently. GitHub labels and marker comments are the coordination surface; local state is a cache.