beads: add wait_for_bead.sh event-driven work discovery

Blocks on anvillm/events, filters BeadReady for matching mount and role,
emits full bead JSON (including comments) and exits. Zero polling, zero
context cost, no supervisor needed for work assignment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-14 20:37:28 +01:00
parent c58f0615a9
commit c3b3d1fd87
2 changed files with 54 additions and 0 deletions

46
mcptools/wait_for_bead.sh Executable file
View File

@ -0,0 +1,46 @@
#!/bin/bash
# capabilities: beads
# description: Block until a bead matching --mount and --role is ready, then print its full JSON (including comments) and exit. Uses the anvillm/events stream — no polling.
# Usage: wait_for_bead.sh --mount <mount> [--role <role>]
set -euo pipefail
MOUNT=""
ROLE="${AGENT_ROLE:-developer}"
while [[ $# -gt 0 ]]; do
case "$1" in
--mount) MOUNT="$2"; shift 2 ;;
--role) ROLE="$2"; shift 2 ;;
*) echo "unknown argument: $1" >&2; exit 1 ;;
esac
done
if [ -z "$MOUNT" ]; then
echo "usage: wait_for_bead.sh --mount <mount> [--role <role>]" >&2
exit 1
fi
EXPECTED_SOURCE="beads/$MOUNT"
9p read anvillm/events | while IFS= read -r line; do
type=$(echo "$line" | jq -r '.type // empty' 2>/dev/null)
[ "$type" = "BeadReady" ] || continue
source=$(echo "$line" | jq -r '.source // empty' 2>/dev/null)
[ "$source" = "$EXPECTED_SOURCE" ] || continue
# Check role label matches (format: "role:<role>")
bead_role=$(echo "$line" | jq -r '
.data.labels // [] |
map(select(startswith("role:"))) |
first // "" |
ltrimstr("role:")
' 2>/dev/null)
# Default to "developer" if no role label
[ -z "$bead_role" ] && bead_role="developer"
[ "$bead_role" = "$ROLE" ] || continue
# Emit full bead data and exit
echo "$line" | jq '.data'
exit 0
done

View File

@ -38,6 +38,14 @@ Tool: execute_code
tool: list_mounts.sh
```
Wait for a bead matching your mount and role (blocks until one is ready, returns full bead JSON including comments, then exits):
```
Tool: execute_code
tool: wait_for_bead.sh
args: ["--mount", "<mount>"]
```
`--role <role>` is optional; defaults to `$AGENT_ROLE` or `developer`.
List ready beads (open, unblocked):
```
Tool: execute_code