Files
gastown/.beads/formulas/mol-witness-patrol.formula.toml
Steve Yegge 0e90fca49f Simplify Witness patrol: linear + Task tool, no Christmas Ornament (gt-p3v5n)
Design pivot:
- Remove mol-polecat-arm and dynamic bonding pattern
- Replace with linear patrol (Deacon-style) + Task tool parallelism
- Cleanup wisps as finalizers (marker wisp = pending cleanup)
- Discovery over tracking (no persistent nudge counts)

New docs:
- polecat-lifecycle.md: step-based restart model, evolution path
- witness-patrol-design.md: simplified, terse

Closed obsolete issues: gt-p3v5n.1 through gt-p3v5n.4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 14:16:41 -08:00

226 lines
6.3 KiB
TOML

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
┌──────────────────────────────────────────────────┘
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
[[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>
```
The wisp's existence IS the pending cleanup. Process in next step.
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."""
[[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:
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 # No unpushed commits
bd show <assigned-issue> # Issue closed or deferred
```
3. **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
4. **If clean**: Execute cleanup
```bash
gt session kill <rig>/polecats/<name>
# Worktree removal handled by session kill
```
Then burn the cleanup wisp:
```bash
bd close <wisp-id> # or bd burn <wisp-id>
```
5. **If dirty**: Leave wisp open, log the issue, retry next cycle.
**Parallelism**: Use Task tool subagents to process multiple cleanups concurrently.
Each cleanup is independent - perfect for parallel execution."""
[[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."""
[[steps]]
id = "survey-workers"
title = "Inspect all active polecats"
needs = ["check-refinery"]
description = """
Survey all polecats and take action on stuck workers.
```bash
gt polecat list <rig>
```
**For each polecat, assess:**
1. **Capture tmux state**:
```bash
tmux capture-pane -t gt-<rig>-<name> -p | tail -50
```
2. **Determine status** (ZFC - you make the judgment):
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **done**: Showing completion indicators (should have sent POLECAT_DONE)
3. **Check beads progress**:
```bash
bd hook --agent <rig>/polecats/<name> # What step are they on?
```
- Has their step changed since you last looked?
- How long on current step? (Check step timestamps)
4. **Decide action** (fresh judgment each cycle, no counters):
| Observation | Action |
|-------------|--------|
| Actively working | None |
| Just started step (<5 min) | None |
| Idle 5-15 min, same step | Gentle nudge |
| Idle 15+ min, same step | Direct nudge with deadline |
| Idle 30+ min despite nudges | Escalate to Mayor |
| Showing errors | Assess severity, help or escalate |
| Says "done" but no POLECAT_DONE | Nudge to send completion mail |
5. **Execute nudges**:
```bash
gt nudge <rig>/polecats/<name> "How's progress on <step>? Need help?"
```
6. **Escalate stuck workers**:
```bash
gt mail send mayor/ -s "Escalation: <polecat> stuck" \
-m "Polecat <name> has been idle on <step> for <duration>.
Nudges ineffective. Please intervene."
```
**Parallelism**: Use Task tool subagents to inspect multiple polecats concurrently.
Launch one subagent per polecat for capture/assess/decide/act cycle.
**No persistent state**: Each cycle is a fresh observation.
"Nudge count" is replaced by "how long stuck on same step" which is discoverable from beads timestamps."""
[[steps]]
id = "context-check"
title = "Check own context limit"
needs = ["survey-workers"]
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"""
[[steps]]
id = "loop-or-exit"
title = "Loop or exit for respawn"
needs = ["context-check"]
description = """
End of patrol cycle decision.
**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."""