feat(deacon): use await-signal with exponential backoff in patrol loop

The Deacon patrol formula now uses `gt mol step await-signal` with
exponential backoff instead of vague "sleep 60s" instructions.

How it works:
- Subscribes to `bd activity --follow` (beads activity feed)
- Returns IMMEDIATELY when any gt/bd command triggers activity
- On timeout, waits exponentially longer: 60s → 120s → 240s → max 10m
- Tracks idle:N label on hq-deacon bead across invocations

This connects the designed-but-unintegrated backoff mechanism to the
actual patrol loop. Idle towns let Deacon sleep; active work wakes it.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gastown/crew/jack
2026-01-09 18:07:07 -08:00
committed by Steve Yegge
parent 7367aa7572
commit ad8189b010
2 changed files with 66 additions and 18 deletions

View File

@@ -23,7 +23,7 @@ Witnesses detect it and escalate to the Mayor.
The Deacon's agent bead last_activity timestamp is updated during each patrol The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.""" cycle. Witnesses check this timestamp to verify health."""
formula = "mol-deacon-patrol" formula = "mol-deacon-patrol"
version = 6 version = 8
[[steps]] [[steps]]
id = "inbox-check" id = "inbox-check"
@@ -707,15 +707,39 @@ Burn and let daemon respawn, or exit if context high.
Decision point at end of patrol cycle: Decision point at end of patrol cycle:
If context is LOW: If context is LOW:
- **Sleep 60 seconds minimum** before next patrol cycle Use await-signal with exponential backoff to wait for activity:
- If town is idle (no in_progress work), sleep longer (2-5 minutes)
- Return to inbox-check step
**Why longer sleep?** ```bash
- Idle agents should not be disturbed gt mol step await-signal --agent-bead hq-deacon \
- Health checks every few seconds flood inboxes and waste context --backoff-base 60s --backoff-mult 2 --backoff-max 10m
- The daemon (10-minute heartbeat) is the safety net for dead sessions ```
- Active work triggers feed events, which wake agents naturally
This command:
1. Subscribes to `bd activity --follow` (beads activity feed)
2. Returns IMMEDIATELY when any beads activity occurs
3. If no activity, times out with exponential backoff:
- First timeout: 60s
- Second timeout: 120s
- Third timeout: 240s
- ...capped at 10 minutes max
4. Tracks `idle:N` label on hq-deacon bead for backoff state
**On signal received** (activity detected):
Reset the idle counter and start next patrol cycle:
```bash
gt agent state hq-deacon --set idle=0
```
Then return to inbox-check step.
**On timeout** (no activity):
The idle counter was auto-incremented. Continue to next patrol cycle
(the longer backoff will apply next time). Return to inbox-check step.
**Why this approach?**
- Any `gt` or `bd` command triggers beads activity, waking the Deacon
- Idle towns let the Deacon sleep longer (up to 10 min between patrols)
- Active work wakes the Deacon immediately via the feed
- No polling or fixed sleep intervals
If context is HIGH: If context is HIGH:
- Write state to persistent storage - Write state to persistent storage

View File

@@ -23,7 +23,7 @@ Witnesses detect it and escalate to the Mayor.
The Deacon's agent bead last_activity timestamp is updated during each patrol The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.""" cycle. Witnesses check this timestamp to verify health."""
formula = "mol-deacon-patrol" formula = "mol-deacon-patrol"
version = 7 version = 8
[[steps]] [[steps]]
id = "inbox-check" id = "inbox-check"
@@ -749,15 +749,39 @@ Burn and let daemon respawn, or exit if context high.
Decision point at end of patrol cycle: Decision point at end of patrol cycle:
If context is LOW: If context is LOW:
- **Sleep 60 seconds minimum** before next patrol cycle Use await-signal with exponential backoff to wait for activity:
- If town is idle (no in_progress work), sleep longer (2-5 minutes)
- Return to inbox-check step
**Why longer sleep?** ```bash
- Idle agents should not be disturbed gt mol step await-signal --agent-bead hq-deacon \
- Health checks every few seconds flood inboxes and waste context --backoff-base 60s --backoff-mult 2 --backoff-max 10m
- The daemon (10-minute heartbeat) is the safety net for dead sessions ```
- Active work triggers feed events, which wake agents naturally
This command:
1. Subscribes to `bd activity --follow` (beads activity feed)
2. Returns IMMEDIATELY when any beads activity occurs
3. If no activity, times out with exponential backoff:
- First timeout: 60s
- Second timeout: 120s
- Third timeout: 240s
- ...capped at 10 minutes max
4. Tracks `idle:N` label on hq-deacon bead for backoff state
**On signal received** (activity detected):
Reset the idle counter and start next patrol cycle:
```bash
gt agent state hq-deacon --set idle=0
```
Then return to inbox-check step.
**On timeout** (no activity):
The idle counter was auto-incremented. Continue to next patrol cycle
(the longer backoff will apply next time). Return to inbox-check step.
**Why this approach?**
- Any `gt` or `bd` command triggers beads activity, waking the Deacon
- Idle towns let the Deacon sleep longer (up to 10 min between patrols)
- Active work wakes the Deacon immediately via the feed
- No polling or fixed sleep intervals
If context is HIGH: If context is HIGH:
- Write state to persistent storage - Write state to persistent storage