diff --git a/.beads/formulas/mol-witness-patrol.formula.toml b/.beads/formulas/mol-witness-patrol.formula.toml index 8c971a97..ba367de2 100644 --- a/.beads/formulas/mol-witness-patrol.formula.toml +++ b/.beads/formulas/mol-witness-patrol.formula.toml @@ -8,7 +8,7 @@ id = 'inbox-check' title = 'Process witness mail' [[steps]] -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/\ngit status # Must be clean\ngit log origin/main..HEAD # Commits should be pushed\nbd show # 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 # 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 /refinery -s \"MERGE_READY \" -m \"Branch: \nIssue: \nPolecat: \nVerified: clean git state, issue closed\"\n```\nThen update the wisp to merge-requested state:\n```bash\nbd update --labels cleanup,polecat:,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." +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)\n\n1. **Extract polecat name** from wisp title/labels\n\n2. **Pre-kill verification**:\n```bash\ncd polecats/\ngit status # Must be clean\ngit log origin/main..HEAD # Commits should be pushed\nbd show # 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 # 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. **Check if MR exists for this branch**:\n```bash\nbd list --type=merge-request --status=open | grep \n```\n\n6a. **If NO MR exists** (ESCALATED/DEFERRED exit):\nPolecat exited without submitting work to merge queue. If clean, nuke immediately:\n```bash\n# If git state is clean (no uncommitted, no unpushed):\ngt polecat nuke /\n\n# Burn the cleanup wisp\nbd close --reason \"nuked (no MR, clean state)\"\n\n# Archive the POLECAT_DONE mail\ngt mail archive \n```\nNo need to wait for MERGED - there's nothing to merge.\n\n6b. **If MR exists and clean**: Send MERGE_READY to refinery\n```bash\ngt mail send /refinery -s \"MERGE_READY \" -m \"Branch: \nIssue: \nPolecat: \nVerified: clean git state, issue closed\"\n```\nThen update the wisp to merge-requested state:\n```bash\nbd update --labels cleanup,polecat:,state:merge-requested\n```\nWait for MERGED confirmation from refinery before nuking.\n\n7. **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' @@ -20,7 +20,7 @@ needs = ['process-cleanups'] title = 'Ensure refinery is alive' [[steps]] -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: `\n- `agent_state: running|idle|stuck|done`\n- `hook_bead: `\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 | Auto-nuke if clean (Step 3a) |\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 # See current step/issue\n```\n\nYou can also verify they're responsive:\n```bash\ntmux capture-pane -t gt-- -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 3a: For idle polecats, auto-nuke if clean**\n\nWhen agent_state=idle, the polecat has no work assigned. Check if it's safe to nuke:\n\n```bash\n# Check git status in the polecat's worktree\ncd polecats/\ngit status --porcelain # Should be empty (clean)\ngit log origin/main..HEAD # Should have no unpushed commits\n```\n\n**If clean** (no uncommitted changes, no unpushed commits):\n```bash\n# Safe to nuke - no work to lose\ngt polecat nuke \n```\nLog the auto-nuke for audit purposes. No escalation needed.\n\n**If dirty** (uncommitted or unpushed work):\n```bash\n# Escalate to Mayor - polecat has work that might be valuable\ngt mail send mayor/ -s \\\"IDLE_DIRTY: has uncommitted work\\\" \\\n -m \\\"Polecat: \nState: idle (no hook_bead)\nGit status: \nUnpushed commits: \n\nPlease advise: recover work or discard?\\\"\n```\n\n**Rationale**: Idle polecats with clean git state are pure overhead. They have\nno work and no state worth preserving. Nuking them immediately frees resources\nand reduces noise. Only escalate when there's actual work at risk.\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: --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:\" --description \"Discovered done polecat without cleanup wisp\" --labels cleanup,polecat:,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 /polecats/ \"How's progress? Need help?\"\n```\n\n**Step 6: Escalate if needed**\n```bash\ngt mail send mayor/ -s \"Escalation: stuck\" \\\n -m \"Polecat 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." +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: `\n- `agent_state: running|idle|stuck|done`\n- `hook_bead: `\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 | Auto-nuke if clean (Step 3a) |\n| stuck | Self-reported stuck | Handle stuck protocol |\n| done | Work complete | Auto-nuke if clean and no MR (Step 3a), else verify cleanup (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 # See current step/issue\n```\n\nYou can also verify they're responsive:\n```bash\ntmux capture-pane -t gt-- -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 3a: For idle or done polecats without MR, auto-nuke if clean**\n\nWhen agent_state=idle OR agent_state=done (with no pending MR), the polecat has\ncompleted its lifecycle. Check if it's safe to nuke:\n\n```bash\n# Check if polecat has a pending MR (only for done state)\nbd list --type=merge-request --status=open | grep \n\n# If MR exists, skip - will be handled via MERGED flow\n# If no MR, check git status in the polecat's worktree:\ncd polecats/\ngit status --porcelain # Should be empty (clean)\ngit log origin/main..HEAD # Should have no unpushed commits\n```\n\n**If clean** (no uncommitted changes, no unpushed commits, no pending MR):\n```bash\n# Safe to nuke - no work to lose\ngt polecat nuke /\n```\nLog the auto-nuke for audit purposes. No escalation needed.\n\n**If dirty** (uncommitted or unpushed work):\n```bash\n# Escalate to Mayor - polecat has work that might be valuable\ngt mail send mayor/ -s \\\"IDLE_DIRTY: has uncommitted work\\\" \\\n -m \\\"Polecat: \nState: (no hook_bead)\nGit status: \nUnpushed commits: \n\nPlease advise: recover work or discard?\\\"\n```\n\n**Rationale**: Polecats with clean git state and no pending MR are pure overhead.\nThey have no work and no state worth preserving. Nuking them immediately frees\nresources and reduces noise. Only escalate when there's actual work at risk.\n\n**Key insight**: agent_state=done with cleanup_status=clean and no MR means the\npolecat exited via ESCALATED/DEFERRED - nuke immediately, don't wait for MERGED.\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\nFirst, check if polecat has a pending MR:\n```bash\nbd list --type=merge-request --status=open | grep \n```\n\n**If NO MR exists** (ESCALATED/DEFERRED exit or already merged):\nThe polecat can be nuked immediately if clean. Check git state and nuke:\n```bash\ngt polecat nuke / # Has safety checks built in\n```\nSkip the cleanup wisp flow entirely - there's nothing to wait for.\n\n**If MR exists** (COMPLETED exit, waiting for merge):\nEnsure cleanup wisp exists:\n```bash\nbd list --wisp --labels=polecat: --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:\" --description \"Discovered done polecat without cleanup wisp\" --labels cleanup,polecat:,state:pending\n```\nThis ensures done polecats with pending MRs eventually get cleaned up.\n\n**Step 5: Execute nudges**\n```bash\ngt nudge /polecats/ \"How's progress? Need help?\"\n```\n\n**Step 6: Escalate if needed**\n```bash\ngt mail send mayor/ -s \"Escalation: stuck\" \\\n -m \"Polecat 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'