Add patrol hygiene: inbox cleanup for Witness/Refinery/Deacon (gt-h5e0)
Each patrol formula now includes: - Explicit archive instructions after processing messages - New patrol-cleanup step for end-of-cycle inbox hygiene - Deacon: log rotation and state.json pruning Changes: - mol-witness-patrol v2: POLECAT_STARTED archive, patrol-cleanup step - mol-refinery-patrol v3: MERGE_READY archive after merge, patrol-cleanup step - mol-deacon-patrol v3: log-maintenance step, patrol-cleanup step 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,7 @@ Witnesses detect it and escalate to the Mayor.
|
||||
The Deacon's agent bead last_activity timestamp is updated during each patrol
|
||||
cycle. Witnesses check this timestamp to verify health."""
|
||||
formula = "mol-deacon-patrol"
|
||||
version = 2
|
||||
version = 3
|
||||
|
||||
[[steps]]
|
||||
id = "inbox-check"
|
||||
@@ -35,16 +35,30 @@ gt mail read <id>
|
||||
|
||||
**WITNESS_PING**:
|
||||
Witnesses periodically ping to verify Deacon is alive. Simply acknowledge
|
||||
and mark as read - the fact that you're processing mail proves you're running.
|
||||
and archive - the fact that you're processing mail proves you're running.
|
||||
Your agent bead last_activity is updated automatically during patrol.
|
||||
```bash
|
||||
gt mail archive <message-id>
|
||||
```
|
||||
|
||||
**HELP / Escalation**:
|
||||
Assess and handle or forward to Mayor.
|
||||
Archive after handling:
|
||||
```bash
|
||||
gt mail archive <message-id>
|
||||
```
|
||||
|
||||
**LIFECYCLE messages**:
|
||||
Polecats reporting completion, refineries reporting merge results.
|
||||
Archive after processing:
|
||||
```bash
|
||||
gt mail archive <message-id>
|
||||
```
|
||||
|
||||
Callbacks may spawn new polecats, update issue state, or trigger other actions."""
|
||||
Callbacks may spawn new polecats, update issue state, or trigger other actions.
|
||||
|
||||
**Hygiene principle**: Archive messages after they're fully processed.
|
||||
Keep inbox near-empty - only unprocessed items should remain."""
|
||||
|
||||
[[steps]]
|
||||
id = "trigger-pending-spawns"
|
||||
@@ -350,10 +364,86 @@ This handles:
|
||||
|
||||
All cleanup is handled by doctor checks - no need to run separate commands."""
|
||||
|
||||
[[steps]]
|
||||
id = "log-maintenance"
|
||||
title = "Rotate logs and prune state"
|
||||
needs = ["session-gc"]
|
||||
description = """
|
||||
Maintain daemon logs and state files.
|
||||
|
||||
**Step 1: Check daemon.log size**
|
||||
```bash
|
||||
# Get log file size
|
||||
ls -la ~/.beads/daemon*.log 2>/dev/null || ls -la ~/gt/.beads/daemon*.log 2>/dev/null
|
||||
```
|
||||
|
||||
If daemon.log exceeds 10MB:
|
||||
```bash
|
||||
# Rotate with date suffix and gzip
|
||||
LOGFILE="$HOME/gt/.beads/daemon.log"
|
||||
if [ -f "$LOGFILE" ] && [ $(stat -f%z "$LOGFILE" 2>/dev/null || stat -c%s "$LOGFILE") -gt 10485760 ]; then
|
||||
DATE=$(date +%Y-%m-%dT%H-%M-%S)
|
||||
mv "$LOGFILE" "${LOGFILE%.log}-${DATE}.log"
|
||||
gzip "${LOGFILE%.log}-${DATE}.log"
|
||||
fi
|
||||
```
|
||||
|
||||
**Step 2: Archive old daemon logs**
|
||||
|
||||
Clean up daemon logs older than 7 days:
|
||||
```bash
|
||||
find ~/gt/.beads/ -name "daemon-*.log.gz" -mtime +7 -delete
|
||||
```
|
||||
|
||||
**Step 3: Prune state.json of dead sessions**
|
||||
|
||||
The state.json tracks active sessions. Prune entries for sessions that no longer exist:
|
||||
```bash
|
||||
# Check for stale session entries
|
||||
gt daemon status --json 2>/dev/null
|
||||
```
|
||||
|
||||
If state.json references sessions not in tmux:
|
||||
- Remove the stale entries
|
||||
- The daemon's internal cleanup should handle this, but verify
|
||||
|
||||
**Note**: Log rotation prevents disk bloat from long-running daemons.
|
||||
State pruning keeps runtime state accurate."""
|
||||
|
||||
[[steps]]
|
||||
id = "patrol-cleanup"
|
||||
title = "End-of-cycle inbox hygiene"
|
||||
needs = ["log-maintenance"]
|
||||
description = """
|
||||
Verify inbox hygiene before ending patrol cycle.
|
||||
|
||||
**Step 1: Check inbox state**
|
||||
```bash
|
||||
gt mail inbox
|
||||
```
|
||||
|
||||
Inbox should be EMPTY or contain only just-arrived unprocessed messages.
|
||||
|
||||
**Step 2: Archive any remaining processed messages**
|
||||
|
||||
All message types should have been archived during inbox-check processing:
|
||||
- WITNESS_PING → archived after acknowledging
|
||||
- HELP/Escalation → archived after handling
|
||||
- LIFECYCLE → archived after processing
|
||||
|
||||
If any were missed:
|
||||
```bash
|
||||
# For each stale message found:
|
||||
gt mail archive <message-id>
|
||||
```
|
||||
|
||||
**Goal**: Inbox should have ≤2 active messages at end of cycle.
|
||||
Deacon mail should flow through quickly - no accumulation."""
|
||||
|
||||
[[steps]]
|
||||
id = "context-check"
|
||||
title = "Check own context limit"
|
||||
needs = ["session-gc"]
|
||||
needs = ["patrol-cleanup"]
|
||||
description = """
|
||||
Check own context limit.
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ Witness Refinery Git
|
||||
After successful merge, Refinery sends MERGED mail back to Witness so it can
|
||||
complete cleanup (nuke the polecat worktree)."""
|
||||
formula = "mol-refinery-patrol"
|
||||
version = 2
|
||||
version = 3
|
||||
|
||||
[[steps]]
|
||||
id = "inbox-check"
|
||||
@@ -65,19 +65,34 @@ A polecat's work is ready for merge. Extract details and track for processing.
|
||||
# - MR bead ID (REQUIRED for closing after merge)
|
||||
```
|
||||
|
||||
**IMPORTANT**: You MUST track the polecat name and MR bead ID - you will need them
|
||||
in merge-push step to send MERGED notification and close the MR bead.
|
||||
**IMPORTANT**: You MUST track the polecat name, MR bead ID, AND message ID - you will need them
|
||||
in merge-push step to send MERGED notification, close the MR bead, and archive the mail.
|
||||
|
||||
Mark as read. The work will be processed in queue-scan/process-branch.
|
||||
**Do NOT archive yet** - archive after merge/reject decision in merge-push step.
|
||||
|
||||
**PATROL: Wake up**:
|
||||
Witness detected MRs waiting but refinery idle. Acknowledge and proceed.
|
||||
Witness detected MRs waiting but refinery idle. Acknowledge and archive:
|
||||
```bash
|
||||
gt mail archive <message-id>
|
||||
```
|
||||
|
||||
**HELP / Blocked**:
|
||||
Assess and respond. If you can't help, escalate to Mayor.
|
||||
Archive after handling:
|
||||
```bash
|
||||
gt mail archive <message-id>
|
||||
```
|
||||
|
||||
**HANDOFF**:
|
||||
Read predecessor context. Check for in-flight merges."""
|
||||
Read predecessor context. Check for in-flight merges.
|
||||
Archive after absorbing context:
|
||||
```bash
|
||||
gt mail archive <message-id>
|
||||
```
|
||||
|
||||
**Hygiene principle**: Archive messages after they're fully processed.
|
||||
Keep only: pending MRs in queue. Inbox should be near-empty."""
|
||||
|
||||
[[steps]]
|
||||
id = "queue-scan"
|
||||
@@ -196,7 +211,13 @@ The MR bead ID was in the MERGE_READY message or find via:
|
||||
bd list --type=merge-request --status=open | grep <polecat-name>
|
||||
```
|
||||
|
||||
**Step 4: Cleanup (only after Steps 2-3 confirmed)**
|
||||
**Step 4: Archive the MERGE_READY mail (REQUIRED)**
|
||||
```bash
|
||||
gt mail archive <merge-ready-message-id>
|
||||
```
|
||||
The message ID was tracked when you processed inbox-check.
|
||||
|
||||
**Step 5: Cleanup (only after Steps 2-4 confirmed)**
|
||||
```bash
|
||||
git branch -d temp
|
||||
git push origin --delete <polecat-branch>
|
||||
@@ -205,8 +226,9 @@ git push origin --delete <polecat-branch>
|
||||
**VERIFICATION GATE**: You CANNOT proceed to loop-check without:
|
||||
- [x] MERGED mail sent to witness
|
||||
- [x] MR bead closed
|
||||
- [x] MERGE_READY mail archived
|
||||
|
||||
If you skipped notifications, GO BACK AND SEND THEM NOW.
|
||||
If you skipped notifications or archiving, GO BACK AND DO THEM NOW.
|
||||
|
||||
Main has moved. Any remaining branches need rebasing on new baseline."""
|
||||
|
||||
@@ -232,13 +254,15 @@ Summarize this patrol cycle.
|
||||
**VERIFICATION**: Before generating summary, confirm for each merged branch:
|
||||
- [ ] MERGED mail was sent to witness
|
||||
- [ ] MR bead was closed
|
||||
- [ ] MERGE_READY mail archived
|
||||
|
||||
If any MERGED notifications were missed, send them now!
|
||||
If any notifications or archiving were missed, do them now!
|
||||
|
||||
Include in summary:
|
||||
- Branches processed (count, names)
|
||||
- MERGED mails sent (count - should match branches processed)
|
||||
- MR beads closed (count - should match branches processed)
|
||||
- MERGE_READY mails archived (count - should match branches processed)
|
||||
- Test results (pass/fail)
|
||||
- Issues filed (if any)
|
||||
- Branches skipped (with reasons)
|
||||
@@ -260,10 +284,41 @@ If context is HIGH (>80%):
|
||||
If context is LOW:
|
||||
- Can continue processing"""
|
||||
|
||||
[[steps]]
|
||||
id = "patrol-cleanup"
|
||||
title = "End-of-cycle inbox hygiene"
|
||||
needs = ["context-check"]
|
||||
description = """
|
||||
Verify inbox hygiene before ending patrol cycle.
|
||||
|
||||
**Step 1: Check inbox state**
|
||||
```bash
|
||||
gt mail inbox
|
||||
```
|
||||
|
||||
Inbox should contain ONLY:
|
||||
- Unprocessed MERGE_READY messages (will process next cycle)
|
||||
- Active work items
|
||||
|
||||
**Step 2: Archive any stale messages**
|
||||
|
||||
Look for messages that were processed but not archived:
|
||||
- PATROL: Wake up that was acknowledged → archive
|
||||
- HELP/Blocked that was handled → archive
|
||||
- MERGE_READY where merge completed but archive was missed → archive
|
||||
|
||||
```bash
|
||||
# For each stale message found:
|
||||
gt mail archive <message-id>
|
||||
```
|
||||
|
||||
**Goal**: Inbox should have ≤3 active messages at end of cycle.
|
||||
Keep only: pending MRs in queue."""
|
||||
|
||||
[[steps]]
|
||||
id = "burn-or-loop"
|
||||
title = "Burn and respawn or loop"
|
||||
needs = ["context-check"]
|
||||
needs = ["patrol-cleanup"]
|
||||
description = """
|
||||
End of patrol cycle decision.
|
||||
|
||||
|
||||
@@ -1,369 +1,56 @@
|
||||
description = """
|
||||
Per-rig worker monitor patrol loop.
|
||||
|
||||
The Witness is the Pit Boss for your rig. You watch polecats, nudge them toward
|
||||
completion, verify clean git state before kills, and escalate stuck workers.
|
||||
|
||||
**You do NOT do implementation work.** Your job is oversight, not coding.
|
||||
|
||||
## Design Philosophy
|
||||
|
||||
This patrol follows Gas Town principles:
|
||||
- **Discovery over tracking**: Observe reality each cycle, don't maintain state
|
||||
- **Events over state**: POLECAT_DONE mail triggers cleanup wisps
|
||||
- **Cleanup wisps as finalizers**: Pending cleanups are wisps, not queue entries
|
||||
- **Task tool for parallelism**: Subagents inspect polecats, not molecule arms
|
||||
|
||||
## Patrol Shape (Linear, Deacon-style)
|
||||
|
||||
```
|
||||
inbox-check ─► process-cleanups ─► check-refinery ─► survey-workers
|
||||
│
|
||||
┌──────────────────────────────────────────────────┘
|
||||
▼
|
||||
check-swarm ─► ping-deacon ─► context-check ─► loop-or-exit
|
||||
```
|
||||
|
||||
No dynamic arms. No fanout gates. No persistent nudge counters.
|
||||
State is discovered each cycle from reality (tmux, beads, mail)."""
|
||||
formula = "mol-witness-patrol"
|
||||
version = 1
|
||||
description = "Per-rig worker monitor patrol loop.\n\nThe Witness is the Pit Boss for your rig. You watch polecats, nudge them toward\ncompletion, verify clean git state before kills, and escalate stuck workers.\n\n**You do NOT do implementation work.** Your job is oversight, not coding.\n\n## Design Philosophy\n\nThis patrol follows Gas Town principles:\n- **Discovery over tracking**: Observe reality each cycle, don't maintain state\n- **Events over state**: POLECAT_DONE mail triggers cleanup wisps\n- **Cleanup wisps as finalizers**: Pending cleanups are wisps, not queue entries\n- **Task tool for parallelism**: Subagents inspect polecats, not molecule arms\n\n## Patrol Shape (Linear, Deacon-style)\n\n```\ninbox-check ─► process-cleanups ─► check-refinery ─► survey-workers\n │\n ┌──────────────────────────────────────────────────┘\n ▼\n check-swarm ─► ping-deacon ─► patrol-cleanup ─► context-check ─► loop-or-exit\n```\n\nNo dynamic arms. No fanout gates. No persistent nudge counters.\nState is discovered each cycle from reality (tmux, beads, mail)."
|
||||
formula = 'mol-witness-patrol'
|
||||
version = 2
|
||||
|
||||
[[steps]]
|
||||
id = "inbox-check"
|
||||
title = "Process witness mail"
|
||||
description = """
|
||||
Check inbox and handle messages.
|
||||
|
||||
```bash
|
||||
gt mail inbox
|
||||
```
|
||||
|
||||
For each message:
|
||||
|
||||
**POLECAT_DONE / LIFECYCLE:Shutdown**:
|
||||
Create a cleanup wisp for this polecat:
|
||||
```bash
|
||||
bd create --wisp --title "cleanup:<polecat>" \
|
||||
--description "Verify and cleanup polecat <name>" \
|
||||
--labels cleanup,polecat:<name>,state:pending
|
||||
```
|
||||
The wisp's existence IS the pending cleanup. Process in next step.
|
||||
Mark mail as read.
|
||||
|
||||
**MERGED**:
|
||||
A branch was merged successfully. Complete the cleanup.
|
||||
```bash
|
||||
# Find the cleanup wisp for this polecat
|
||||
bd list --wisp --labels=polecat:<name>,state:merge-requested --status=open
|
||||
|
||||
# If found, proceed with full polecat nuke:
|
||||
# - Kill Claude session
|
||||
# - Delete worktree
|
||||
# - Delete branch
|
||||
# - Remove agent bead
|
||||
gt polecat nuke <name>
|
||||
|
||||
# Burn the cleanup wisp
|
||||
bd close <wisp-id>
|
||||
```
|
||||
Mark mail as read.
|
||||
|
||||
**HELP / Blocked**:
|
||||
Assess the request. Can you help? If not, escalate to Mayor:
|
||||
```bash
|
||||
gt mail send mayor/ -s "Escalation: <polecat> needs help" -m "<details>"
|
||||
```
|
||||
|
||||
**HANDOFF**:
|
||||
Read predecessor context. Continue from where they left off.
|
||||
|
||||
**SWARM_START**:
|
||||
Mayor initiating batch polecat work. Initialize swarm tracking.
|
||||
```bash
|
||||
# Parse swarm info from mail body: {"swarm_id": "batch-123", "beads": ["bd-a", "bd-b"]}
|
||||
bd create --wisp --title "swarm:<swarm_id>" \
|
||||
--description "Tracking batch: <swarm_id>" \
|
||||
--labels swarm,swarm_id:<swarm_id>,total:<N>,completed:0,start:<timestamp>
|
||||
```
|
||||
Mark mail as read."""
|
||||
description = "Check inbox and handle messages.\n\n```bash\ngt mail inbox\n```\n\nFor each message:\n\n**POLECAT_STARTED**:\nA new polecat has started working. Acknowledge and archive.\n```bash\n# Acknowledge startup (optional: log for activity tracking)\ngt mail archive <message-id>\n```\nNo action needed beyond acknowledgment - archive immediately.\n\n**POLECAT_DONE / LIFECYCLE:Shutdown**:\nCreate a cleanup wisp for this polecat:\n```bash\nbd create --wisp --title \"cleanup:<polecat>\" --description \"Verify and cleanup polecat <name>\" --labels cleanup,polecat:<name>,state:pending\n```\nThe wisp's existence IS the pending cleanup. Process in next step.\n**Do NOT archive yet** - archive after cleanup completes (in MERGED handling).\n\n**MERGED**:\nA branch was merged successfully. Complete the cleanup.\n```bash\n# Find the cleanup wisp for this polecat\nbd list --wisp --labels=polecat:<name>,state:merge-requested --status=open\n\n# If found, proceed with full polecat nuke:\n# - Kill Claude session\n# - Delete worktree\n# - Delete branch\n# - Remove agent bead\ngt polecat nuke <name>\n\n# Burn the cleanup wisp\nbd close <wisp-id>\n\n# NOW archive both the MERGED mail and the original POLECAT_DONE mail\n# (The POLECAT_DONE message ID should be tracked in the cleanup wisp or MR bead)\ngt mail archive <merged-message-id>\ngt mail archive <polecat-done-message-id> # If tracked\n```\nArchive after cleanup is complete.\n\n**HELP / Blocked**:\nAssess the request. Can you help? If not, escalate to Mayor:\n```bash\ngt mail send mayor/ -s \"Escalation: <polecat> needs help\" -m \"<details>\"\n```\nArchive after handling (escalated or resolved):\n```bash\ngt mail archive <message-id>\n```\n\n**HANDOFF**:\nRead predecessor context. Continue from where they left off.\nArchive after absorbing context:\n```bash\ngt mail archive <message-id>\n```\n\n**SWARM_START**:\nMayor initiating batch polecat work. Initialize swarm tracking.\n```bash\n# Parse swarm info from mail body: {\"swarm_id\": \"batch-123\", \"beads\": [\"bd-a\", \"bd-b\"]}\nbd create --wisp --title \"swarm:<swarm_id>\" --description \"Tracking batch: <swarm_id>\" --labels swarm,swarm_id:<swarm_id>,total:<N>,completed:0,start:<timestamp>\n```\nArchive after creating swarm tracking wisp:\n```bash\ngt mail archive <message-id>\n```\n\n**Hygiene principle**: Archive messages after they're fully processed.\nKeep only: active work, unprocessed requests. Inbox should be near-empty."
|
||||
id = 'inbox-check'
|
||||
title = 'Process witness mail'
|
||||
|
||||
[[steps]]
|
||||
id = "process-cleanups"
|
||||
title = "Process pending cleanup wisps"
|
||||
needs = ["inbox-check"]
|
||||
description = """
|
||||
Find and process cleanup wisps (the finalizer pattern).
|
||||
|
||||
```bash
|
||||
# Find all cleanup wisps
|
||||
bd list --wisp --labels=cleanup --status=open
|
||||
```
|
||||
|
||||
For each cleanup wisp, check its state label:
|
||||
|
||||
## State: pending (needs verification → MERGE_READY)
|
||||
|
||||
1. **Extract polecat name** from wisp title/labels
|
||||
|
||||
2. **Pre-kill verification**:
|
||||
```bash
|
||||
cd polecats/<name>
|
||||
git status # Must be clean
|
||||
git log origin/main..HEAD # Commits should be pushed
|
||||
bd show <assigned-issue> # Issue closed or deferred
|
||||
```
|
||||
|
||||
3. **Get branch and issue info**:
|
||||
```bash
|
||||
# Get current branch
|
||||
git rev-parse --abbrev-ref HEAD
|
||||
|
||||
# Get the hook_bead from agent bead
|
||||
bd show <agent-bead> # Look for hook_bead field
|
||||
```
|
||||
|
||||
4. **Verify productive work** (ZFC - you make the call):
|
||||
- Check git log for commits mentioning the issue
|
||||
- Legitimate exceptions: already fixed, duplicate, deferred
|
||||
- If closing as 'done' with no commits, flag for review
|
||||
|
||||
5. **If clean**: Send MERGE_READY to refinery
|
||||
```bash
|
||||
gt mail send <rig>/refinery -s "MERGE_READY <polecat>" -m "Branch: <branch>
|
||||
Issue: <issue-id>
|
||||
Polecat: <polecat>
|
||||
Verified: clean git state, issue closed"
|
||||
```
|
||||
Then update the wisp to merge-requested state:
|
||||
```bash
|
||||
bd update <wisp-id> --labels cleanup,polecat:<name>,state:merge-requested
|
||||
```
|
||||
**Do NOT kill the polecat yet** - wait for MERGED confirmation from refinery.
|
||||
|
||||
6. **If dirty**: Leave wisp open, log the issue, retry next cycle.
|
||||
|
||||
## State: merge-requested (waiting for refinery)
|
||||
|
||||
Skip - waiting for MERGED mail from refinery. The inbox-check step handles
|
||||
MERGED messages and completes these cleanup wisps.
|
||||
|
||||
**Parallelism**: Use Task tool subagents to process multiple cleanups concurrently.
|
||||
Each cleanup is independent - perfect for parallel execution."""
|
||||
description = "Find and process cleanup wisps (the finalizer pattern).\n\n```bash\n# Find all cleanup wisps\nbd list --wisp --labels=cleanup --status=open\n```\n\nFor each cleanup wisp, check its state label:\n\n## State: pending (needs verification → MERGE_READY)\n\n1. **Extract polecat name** from wisp title/labels\n\n2. **Pre-kill verification**:\n```bash\ncd polecats/<name>\ngit status # Must be clean\ngit log origin/main..HEAD # Commits should be pushed\nbd show <assigned-issue> # Issue closed or deferred\n```\n\n3. **Get branch and issue info**:\n```bash\n# Get current branch\ngit rev-parse --abbrev-ref HEAD\n\n# Get the hook_bead from agent bead\nbd show <agent-bead> # Look for hook_bead field\n```\n\n4. **Verify productive work** (ZFC - you make the call):\n - Check git log for commits mentioning the issue\n - Legitimate exceptions: already fixed, duplicate, deferred\n - If closing as 'done' with no commits, flag for review\n\n5. **If clean**: Send MERGE_READY to refinery\n```bash\ngt mail send <rig>/refinery -s \"MERGE_READY <polecat>\" -m \"Branch: <branch>\nIssue: <issue-id>\nPolecat: <polecat>\nVerified: clean git state, issue closed\"\n```\nThen update the wisp to merge-requested state:\n```bash\nbd update <wisp-id> --labels cleanup,polecat:<name>,state:merge-requested\n```\n**Do NOT kill the polecat yet** - wait for MERGED confirmation from refinery.\n\n6. **If dirty**: Leave wisp open, log the issue, retry next cycle.\n\n## State: merge-requested (waiting for refinery)\n\nSkip - waiting for MERGED mail from refinery. The inbox-check step handles\nMERGED messages and completes these cleanup wisps.\n\n**Parallelism**: Use Task tool subagents to process multiple cleanups concurrently.\nEach cleanup is independent - perfect for parallel execution."
|
||||
id = 'process-cleanups'
|
||||
needs = ['inbox-check']
|
||||
title = 'Process pending cleanup wisps'
|
||||
|
||||
[[steps]]
|
||||
id = "check-refinery"
|
||||
title = "Ensure refinery is alive"
|
||||
needs = ["process-cleanups"]
|
||||
description = """
|
||||
Ensure the refinery is alive and processing merge requests.
|
||||
|
||||
```bash
|
||||
# Check if refinery session exists
|
||||
gt session status <rig>/refinery
|
||||
|
||||
# Check for pending merge requests
|
||||
bd list --type=merge-request --status=open
|
||||
```
|
||||
|
||||
If MRs waiting AND refinery not running:
|
||||
```bash
|
||||
gt session start <rig>/refinery
|
||||
gt mail send <rig>/refinery -s "PATROL: Wake up" \
|
||||
-m "Merge requests in queue. Please process."
|
||||
```
|
||||
|
||||
If refinery running but queue stale (>30 min), send nudge."""
|
||||
description = "Ensure the refinery is alive and processing merge requests.\n\n```bash\n# Check if refinery session exists\ngt session status <rig>/refinery\n\n# Check for pending merge requests\nbd list --type=merge-request --status=open\n```\n\nIf MRs waiting AND refinery not running:\n```bash\ngt session start <rig>/refinery\ngt mail send <rig>/refinery -s \"PATROL: Wake up\" -m \"Merge requests in queue. Please process.\"\n```\n\nIf refinery running but queue stale (>30 min), send nudge."
|
||||
id = 'check-refinery'
|
||||
needs = ['process-cleanups']
|
||||
title = 'Ensure refinery is alive'
|
||||
|
||||
[[steps]]
|
||||
id = "survey-workers"
|
||||
title = "Inspect all active polecats"
|
||||
needs = ["check-refinery"]
|
||||
description = """
|
||||
Survey all polecats using agent beads (ZFC: trust what agents report).
|
||||
|
||||
**Step 1: List polecat agent beads**
|
||||
|
||||
```bash
|
||||
bd list --type=agent --json
|
||||
```
|
||||
|
||||
Filter the JSON output for entries where description contains `role_type: polecat`.
|
||||
Each polecat agent bead has fields in its description:
|
||||
- `role_type: polecat`
|
||||
- `rig: <rig-name>`
|
||||
- `agent_state: running|idle|stuck|done`
|
||||
- `hook_bead: <current-work-id>`
|
||||
|
||||
**Step 2: For each polecat, check agent_state**
|
||||
|
||||
| agent_state | Meaning | Action |
|
||||
|-------------|---------|--------|
|
||||
| running | Actively working | Check progress (Step 3) |
|
||||
| idle | No work assigned | Skip (no action needed) |
|
||||
| stuck | Self-reported stuck | Handle stuck protocol |
|
||||
| done | Work complete | Verify cleanup triggered (see Step 4a) |
|
||||
|
||||
**Step 3: For running polecats, assess progress**
|
||||
|
||||
Check the hook_bead field to see what they're working on:
|
||||
```bash
|
||||
bd show <hook_bead> # See current step/issue
|
||||
```
|
||||
|
||||
You can also verify they're responsive:
|
||||
```bash
|
||||
tmux capture-pane -t gt-<rig>-<name> -p | tail -20
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Recent tool activity → making progress
|
||||
- Idle at prompt → may need nudge
|
||||
- Error messages → may need help
|
||||
|
||||
**Step 4: Decide action**
|
||||
|
||||
| Observation | Action |
|
||||
|-------------|--------|
|
||||
| agent_state=running, recent activity | None |
|
||||
| agent_state=running, idle 5-15 min | Gentle nudge |
|
||||
| agent_state=running, idle 15+ min | Direct nudge with deadline |
|
||||
| agent_state=stuck | Assess and help or escalate |
|
||||
| agent_state=done | Verify cleanup triggered (see Step 4a) |
|
||||
|
||||
**Step 4a: Handle agent_state=done**
|
||||
|
||||
Check if a cleanup wisp exists for this polecat:
|
||||
```bash
|
||||
bd list --wisp --labels=polecat:<name> --status=open
|
||||
```
|
||||
|
||||
If cleanup wisp exists:
|
||||
- state:pending → Will be processed in process-cleanups
|
||||
- state:merge-requested → Waiting for refinery MERGED response
|
||||
|
||||
If NO cleanup wisp exists (POLECAT_DONE mail missed):
|
||||
Create one to trigger the cleanup flow:
|
||||
```bash
|
||||
bd create --wisp --title "cleanup:<polecat>" \
|
||||
--description "Discovered done polecat without cleanup wisp" \
|
||||
--labels cleanup,polecat:<name>,state:pending
|
||||
```
|
||||
This ensures done polecats eventually get cleaned up even if mail was lost.
|
||||
|
||||
**Step 5: Execute nudges**
|
||||
```bash
|
||||
gt nudge <rig>/polecats/<name> "How's progress? Need help?"
|
||||
```
|
||||
|
||||
**Step 6: Escalate if needed**
|
||||
```bash
|
||||
gt mail send mayor/ -s "Escalation: <polecat> stuck" \\
|
||||
-m "Polecat <name> reports stuck. Please intervene."
|
||||
```
|
||||
|
||||
**Parallelism**: Use Task tool subagents to inspect multiple polecats concurrently.
|
||||
|
||||
**ZFC Principle**: Trust agent_state from beads. Don't infer state from PID/tmux."""
|
||||
description = "Survey all polecats using agent beads (ZFC: trust what agents report).\n\n**Step 1: List polecat agent beads**\n\n```bash\nbd list --type=agent --json\n```\n\nFilter the JSON output for entries where description contains `role_type: polecat`.\nEach polecat agent bead has fields in its description:\n- `role_type: polecat`\n- `rig: <rig-name>`\n- `agent_state: running|idle|stuck|done`\n- `hook_bead: <current-work-id>`\n\n**Step 2: For each polecat, check agent_state**\n\n| agent_state | Meaning | Action |\n|-------------|---------|--------|\n| running | Actively working | Check progress (Step 3) |\n| idle | No work assigned | Skip (no action needed) |\n| stuck | Self-reported stuck | Handle stuck protocol |\n| done | Work complete | Verify cleanup triggered (see Step 4a) |\n\n**Step 3: For running polecats, assess progress**\n\nCheck the hook_bead field to see what they're working on:\n```bash\nbd show <hook_bead> # See current step/issue\n```\n\nYou can also verify they're responsive:\n```bash\ntmux capture-pane -t gt-<rig>-<name> -p | tail -20\n```\n\nLook for:\n- Recent tool activity → making progress\n- Idle at prompt → may need nudge\n- Error messages → may need help\n\n**Step 4: Decide action**\n\n| Observation | Action |\n|-------------|--------|\n| agent_state=running, recent activity | None |\n| agent_state=running, idle 5-15 min | Gentle nudge |\n| agent_state=running, idle 15+ min | Direct nudge with deadline |\n| agent_state=stuck | Assess and help or escalate |\n| agent_state=done | Verify cleanup triggered (see Step 4a) |\n\n**Step 4a: Handle agent_state=done**\n\nCheck if a cleanup wisp exists for this polecat:\n```bash\nbd list --wisp --labels=polecat:<name> --status=open\n```\n\nIf cleanup wisp exists:\n- state:pending → Will be processed in process-cleanups\n- state:merge-requested → Waiting for refinery MERGED response\n\nIf NO cleanup wisp exists (POLECAT_DONE mail missed):\nCreate one to trigger the cleanup flow:\n```bash\nbd create --wisp --title \"cleanup:<polecat>\" --description \"Discovered done polecat without cleanup wisp\" --labels cleanup,polecat:<name>,state:pending\n```\nThis ensures done polecats eventually get cleaned up even if mail was lost.\n\n**Step 5: Execute nudges**\n```bash\ngt nudge <rig>/polecats/<name> \"How's progress? Need help?\"\n```\n\n**Step 6: Escalate if needed**\n```bash\ngt mail send mayor/ -s \"Escalation: <polecat> stuck\" \\\n -m \"Polecat <name> reports stuck. Please intervene.\"\n```\n\n**Parallelism**: Use Task tool subagents to inspect multiple polecats concurrently.\n\n**ZFC Principle**: Trust agent_state from beads. Don't infer state from PID/tmux."
|
||||
id = 'survey-workers'
|
||||
needs = ['check-refinery']
|
||||
title = 'Inspect all active polecats'
|
||||
|
||||
[[steps]]
|
||||
id = "check-swarm-completion"
|
||||
title = "Check if active swarm is complete"
|
||||
needs = ["survey-workers"]
|
||||
description = """
|
||||
If Mayor started a batch (SWARM_START), check if all polecats have completed.
|
||||
|
||||
**Step 1: Find active swarm tracking wisps**
|
||||
```bash
|
||||
bd list --wisp --labels=swarm --status=open
|
||||
```
|
||||
If no active swarm, skip this step.
|
||||
|
||||
**Step 2: Count completed polecats for this swarm**
|
||||
|
||||
Extract from wisp labels: swarm_id, total, completed, start timestamp.
|
||||
Check how many cleanup wisps have been closed for this swarm's polecats.
|
||||
|
||||
**Step 3: If all complete, notify Mayor**
|
||||
```bash
|
||||
gt mail send mayor/ -s "SWARM_COMPLETE: <swarm_id>" -m "All <total> polecats merged.
|
||||
Duration: <minutes> minutes
|
||||
Swarm: <swarm_id>"
|
||||
|
||||
# Close the swarm tracking wisp
|
||||
bd close <swarm-wisp-id> --reason "All polecats merged"
|
||||
```
|
||||
|
||||
Note: Runs every patrol cycle. Notification sent exactly once when all complete."""
|
||||
description = "If Mayor started a batch (SWARM_START), check if all polecats have completed.\n\n**Step 1: Find active swarm tracking wisps**\n```bash\nbd list --wisp --labels=swarm --status=open\n```\nIf no active swarm, skip this step.\n\n**Step 2: Count completed polecats for this swarm**\n\nExtract from wisp labels: swarm_id, total, completed, start timestamp.\nCheck how many cleanup wisps have been closed for this swarm's polecats.\n\n**Step 3: If all complete, notify Mayor**\n```bash\ngt mail send mayor/ -s \"SWARM_COMPLETE: <swarm_id>\" -m \"All <total> polecats merged.\nDuration: <minutes> minutes\nSwarm: <swarm_id>\"\n\n# Close the swarm tracking wisp\nbd close <swarm-wisp-id> --reason \"All polecats merged\"\n```\n\nNote: Runs every patrol cycle. Notification sent exactly once when all complete."
|
||||
id = 'check-swarm-completion'
|
||||
needs = ['survey-workers']
|
||||
title = 'Check if active swarm is complete'
|
||||
|
||||
[[steps]]
|
||||
id = "ping-deacon"
|
||||
title = "Ping Deacon for health check"
|
||||
needs = ["check-swarm-completion"]
|
||||
description = """
|
||||
Send WITNESS_PING to Deacon for second-order monitoring.
|
||||
|
||||
The Witness fleet collectively monitors Deacon health - this prevents the
|
||||
"who watches the watchers" problem. If Deacon dies, Witnesses detect it.
|
||||
|
||||
**Step 1: Send ping**
|
||||
```bash
|
||||
gt mail send deacon/ -s "WITNESS_PING <rig>" -m "Rig: <rig>
|
||||
Timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
Patrol: <cycle-number>"
|
||||
```
|
||||
|
||||
**Step 2: Check Deacon health**
|
||||
```bash
|
||||
# Check Deacon agent bead for last_activity
|
||||
bd list --type=agent --json | jq '.[] | select(.description | contains("deacon"))'
|
||||
```
|
||||
|
||||
Look at the `last_activity` timestamp. If stale (>5 minutes since last update):
|
||||
- Deacon may be dead or stuck
|
||||
|
||||
**Step 3: Escalate if needed**
|
||||
```bash
|
||||
# If Deacon appears down
|
||||
gt mail send mayor/ -s "ALERT: Deacon appears unresponsive" \
|
||||
-m "No Deacon activity for >5 minutes.
|
||||
Last seen: <timestamp>
|
||||
Witness: <rig>/witness"
|
||||
```
|
||||
|
||||
Note: Multiple Witnesses may send this alert. Mayor should handle deduplication."""
|
||||
description = "Send WITNESS_PING to Deacon for second-order monitoring.\n\nThe Witness fleet collectively monitors Deacon health - this prevents the\n\"who watches the watchers\" problem. If Deacon dies, Witnesses detect it.\n\n**Step 1: Send ping**\n```bash\ngt mail send deacon/ -s \"WITNESS_PING <rig>\" -m \"Rig: <rig>\nTimestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)\nPatrol: <cycle-number>\"\n```\n\n**Step 2: Check Deacon health**\n```bash\n# Check Deacon agent bead for last_activity\nbd list --type=agent --json | jq '.[] | select(.description | contains(\"deacon\"))'\n```\n\nLook at the `last_activity` timestamp. If stale (>5 minutes since last update):\n- Deacon may be dead or stuck\n\n**Step 3: Escalate if needed**\n```bash\n# If Deacon appears down\ngt mail send mayor/ -s \"ALERT: Deacon appears unresponsive\" -m \"No Deacon activity for >5 minutes.\nLast seen: <timestamp>\nWitness: <rig>/witness\"\n```\n\nNote: Multiple Witnesses may send this alert. Mayor should handle deduplication."
|
||||
id = 'ping-deacon'
|
||||
needs = ['check-swarm-completion']
|
||||
title = 'Ping Deacon for health check'
|
||||
|
||||
[[steps]]
|
||||
id = "context-check"
|
||||
title = "Check own context limit"
|
||||
needs = ["ping-deacon"]
|
||||
description = """
|
||||
Check own context usage.
|
||||
|
||||
If context is HIGH (>80%):
|
||||
- Ensure any notes are written to handoff mail
|
||||
- Prepare for session restart
|
||||
|
||||
If context is LOW:
|
||||
- Can continue patrolling"""
|
||||
description = "Verify inbox hygiene before ending patrol cycle.\n\n**Step 1: Check inbox state**\n```bash\ngt mail inbox\n```\n\nInbox should contain ONLY:\n- Unprocessed messages (just arrived, will handle next cycle)\n- Active work markers (POLECAT_DONE waiting for MERGED confirmation)\n\n**Step 2: Archive any stale messages**\n\nLook for messages that were processed but not archived:\n- POLECAT_STARTED older than this cycle → archive\n- HELP/Blocked that was escalated → archive\n- SWARM_START that created tracking wisp → archive\n\n```bash\n# For each stale message found:\ngt mail archive <message-id>\n```\n\n**Step 3: Verify cleanup wisp hygiene**\n\nCheck that all cleanup wisps are in valid states:\n```bash\nbd list --wisp --labels=cleanup --status=open\n```\n\n- state:pending → Will be processed next cycle\n- state:merge-requested → Waiting for refinery\n\nIf any cleanup wisp is older than expected (>1 hour in merge-requested state),\nthe refinery may be stuck. This was checked in check-refinery step.\n\n**Goal**: Inbox should have ≤5 active messages at end of cycle."
|
||||
id = 'patrol-cleanup'
|
||||
needs = ['ping-deacon']
|
||||
title = 'End-of-cycle inbox hygiene'
|
||||
|
||||
[[steps]]
|
||||
id = "loop-or-exit"
|
||||
title = "Loop or exit for respawn"
|
||||
needs = ["context-check"]
|
||||
description = """
|
||||
End of patrol cycle decision.
|
||||
description = "Check own context usage.\n\nIf context is HIGH (>80%):\n- Ensure any notes are written to handoff mail\n- Prepare for session restart\n\nIf context is LOW:\n- Can continue patrolling"
|
||||
id = 'context-check'
|
||||
needs = ['patrol-cleanup']
|
||||
title = 'Check own context limit'
|
||||
|
||||
**If context LOW**:
|
||||
- Sleep briefly to avoid tight loop (30-60 seconds)
|
||||
- Return to inbox-check step
|
||||
- Continue patrolling
|
||||
|
||||
**If context HIGH**:
|
||||
- Write handoff mail to self with any notable observations:
|
||||
```bash
|
||||
gt handoff -s "Witness patrol handoff" -m "<observations>"
|
||||
```
|
||||
- Exit cleanly (daemon respawns fresh Witness)
|
||||
|
||||
The daemon ensures Witness is always running."""
|
||||
[[steps]]
|
||||
description = "End of patrol cycle decision.\n\n**If context LOW**:\n- Sleep briefly to avoid tight loop (30-60 seconds)\n- Return to inbox-check step\n- Continue patrolling\n\n**If context HIGH**:\n- Write handoff mail to self with any notable observations:\n```bash\ngt handoff -s \"Witness patrol handoff\" -m \"<observations>\"\n```\n- Exit cleanly (daemon respawns fresh Witness)\n\nThe daemon ensures Witness is always running."
|
||||
id = 'loop-or-exit'
|
||||
needs = ['context-check']
|
||||
title = 'Loop or exit for respawn'
|
||||
|
||||
Reference in New Issue
Block a user