PROBLEM: Agents were reading formula files directly and manually creating beads for each step, rather than using the cook→pour→molecule pipeline. FIXES: - polecat-CLAUDE.md: Changed "following the formula" to "work through your pinned molecule" and added explicit anti-pattern warning - mol-polecat-work.formula.toml: Added note that formula defines template, use bd ready to find step beads - docs/molecules.md: Added "Common Mistake" section with WRONG/RIGHT examples - mol-*.formula.toml (5 files): Changed "execute this formula" to "work through molecules (poured from this formula)" The key insight: Formulas are source templates (like source code). You never read them directly. The cook → pour pipeline creates step beads for you. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
313 lines
7.3 KiB
TOML
313 lines
7.3 KiB
TOML
description = """
|
|
Find and reassign orphaned work.
|
|
|
|
Dogs work through molecules (poured from this formula) to scan for orphaned state:
|
|
- Issues marked in_progress with no active polecat
|
|
- Molecules attached but worker gone
|
|
- Merge queue entries with dead owners
|
|
- Wisps from terminated sessions
|
|
|
|
This is a cleanup and recovery formula. Found orphans are either:
|
|
- Reassigned to available workers
|
|
- Reset to open status for next dispatch
|
|
- Escalated if data loss occurred
|
|
|
|
## Dog Contract
|
|
|
|
This is infrastructure work. You:
|
|
1. Receive scan scope via hook_bead (rig or town-wide)
|
|
2. Scan for orphaned state
|
|
3. Classify and triage orphans
|
|
4. Take recovery action
|
|
5. Report findings
|
|
6. Return to kennel
|
|
|
|
## Variables
|
|
|
|
| Variable | Source | Description |
|
|
|----------|--------|-------------|
|
|
| scope | hook_bead | Scan scope: 'town' or specific rig name |
|
|
|
|
## Why Dogs?
|
|
|
|
Orphan scanning requires multi-rig access and may need to interact with
|
|
multiple Witnesses. Dogs have the cross-rig worktrees needed for this."""
|
|
formula = "mol-orphan-scan"
|
|
version = 1
|
|
|
|
[squash]
|
|
trigger = "on_complete"
|
|
template_type = "work"
|
|
include_metrics = true
|
|
|
|
[[steps]]
|
|
id = "determine-scope"
|
|
title = "Determine scan scope"
|
|
description = """
|
|
Establish what to scan for orphans.
|
|
|
|
**1. Check assignment:**
|
|
```bash
|
|
gt hook # Shows scope in hook_bead
|
|
```
|
|
|
|
**2. Resolve scope:**
|
|
- 'town': Scan all rigs
|
|
- '<rig>': Scan specific rig only
|
|
|
|
```bash
|
|
# If town-wide
|
|
gt rigs # Get list of all rigs
|
|
|
|
# If specific rig
|
|
# Just use that rig
|
|
```
|
|
|
|
**Exit criteria:** Scope determined, rig list established."""
|
|
|
|
[[steps]]
|
|
id = "scan-orphaned-issues"
|
|
title = "Scan for orphaned issues"
|
|
needs = ["determine-scope"]
|
|
description = """
|
|
Find issues marked in_progress with no active worker.
|
|
|
|
**1. For each rig in scope, find in_progress issues:**
|
|
```bash
|
|
bd list --status=in_progress
|
|
```
|
|
|
|
**2. For each in_progress issue, check assignee:**
|
|
```bash
|
|
bd show <issue-id>
|
|
# Get assignee field
|
|
```
|
|
|
|
**3. Check if assignee session exists:**
|
|
```bash
|
|
# If assignee is a polecat
|
|
gt polecats <rig> # Is the polecat active?
|
|
tmux has-session -t <session> 2>/dev/null
|
|
```
|
|
|
|
**4. Identify orphans:**
|
|
- Issue in_progress + assignee session dead = orphan
|
|
- Issue in_progress + no assignee = orphan
|
|
|
|
Record each orphan with:
|
|
- Issue ID
|
|
- Last assignee (if any)
|
|
- How long orphaned (last update timestamp)
|
|
|
|
**Exit criteria:** Orphaned issues identified."""
|
|
|
|
[[steps]]
|
|
id = "scan-orphaned-molecules"
|
|
title = "Scan for orphaned molecules"
|
|
needs = ["determine-scope"]
|
|
description = """
|
|
Find molecules attached to dead sessions.
|
|
|
|
**1. List active molecules:**
|
|
```bash
|
|
bd mol list --active
|
|
```
|
|
|
|
**2. For each molecule, check owner session:**
|
|
```bash
|
|
bd mol show <mol-id>
|
|
# Get agent/session info
|
|
```
|
|
|
|
**3. Check if owner session exists:**
|
|
```bash
|
|
tmux has-session -t <session> 2>/dev/null
|
|
```
|
|
|
|
**4. Identify orphans:**
|
|
- Molecule in_progress + owner session dead = orphan
|
|
- Molecule hooked + owner session dead = orphan
|
|
|
|
Record each orphan for triage.
|
|
|
|
**Exit criteria:** Orphaned molecules identified."""
|
|
|
|
[[steps]]
|
|
id = "scan-orphaned-wisps"
|
|
title = "Scan for orphaned wisps"
|
|
needs = ["determine-scope"]
|
|
description = """
|
|
Find wisps from terminated sessions.
|
|
|
|
**1. List wisps in ephemeral storage:**
|
|
```bash
|
|
ls .beads-wisp/ # Or equivalent location
|
|
```
|
|
|
|
**2. For each wisp, check spawner session:**
|
|
Wisps should have metadata indicating the spawning session.
|
|
|
|
**3. Identify orphans:**
|
|
- Wisp age > 1 hour + spawner session dead = orphan
|
|
- Wisp with no spawner metadata = orphan
|
|
|
|
**4. Check for unsquashed content:**
|
|
Orphaned wisps may have audit-worthy content that wasn't squashed.
|
|
|
|
**Exit criteria:** Orphaned wisps identified."""
|
|
|
|
[[steps]]
|
|
id = "triage-orphans"
|
|
title = "Classify and triage orphans"
|
|
needs = ["scan-orphaned-issues", "scan-orphaned-molecules", "scan-orphaned-wisps"]
|
|
description = """
|
|
Classify orphans by severity and determine action.
|
|
|
|
**1. Classify by type:**
|
|
|
|
| Type | Severity | Typical Action |
|
|
|------|----------|----------------|
|
|
| Issue in_progress, no work done | Low | Reset to open |
|
|
| Issue in_progress, work in progress | Medium | Check branch, reassign |
|
|
| Molecule mid-execution | Medium | Resume or restart |
|
|
| Wisp with content | Low | Squash or burn |
|
|
| Wisp empty | None | Delete |
|
|
|
|
**2. Check for data loss:**
|
|
For issues/molecules with possible work:
|
|
```bash
|
|
# Check for branch with work
|
|
git branch -a | grep <polecat-or-issue>
|
|
git log --oneline <branch>
|
|
```
|
|
|
|
**3. Categorize for action:**
|
|
- RESET: Return to open status for normal dispatch
|
|
- REASSIGN: Assign to specific worker immediately
|
|
- RECOVER: Salvage work from branch/state
|
|
- ESCALATE: Data loss or complex situation
|
|
- BURN: Safe to delete (empty wisps, etc.)
|
|
|
|
**Exit criteria:** All orphans categorized with planned action."""
|
|
|
|
[[steps]]
|
|
id = "execute-recovery"
|
|
title = "Execute recovery actions"
|
|
needs = ["triage-orphans"]
|
|
description = """
|
|
Take action on each orphan based on triage.
|
|
|
|
**1. RESET orphans:**
|
|
```bash
|
|
bd update <issue> --status=open --assignee=""
|
|
# Clears in_progress, ready for dispatch
|
|
```
|
|
|
|
**2. REASSIGN orphans:**
|
|
```bash
|
|
# Notify Witness to handle assignment
|
|
gt mail send <rig>/witness -s "Orphan needs assignment: <issue>" \
|
|
-m "Issue <id> was orphaned. Has partial work. Needs reassignment."
|
|
```
|
|
|
|
**3. RECOVER orphans:**
|
|
```bash
|
|
# For issues with work on branch:
|
|
# - Preserve the branch
|
|
# - Create recovery note
|
|
bd update <issue> --status=open \
|
|
--note="Recovery: work exists on branch <branch>"
|
|
```
|
|
|
|
**4. ESCALATE orphans:**
|
|
```bash
|
|
gt mail send mayor/ -s "Orphan requires escalation: <issue>" \
|
|
-m "Issue <id> orphaned with possible data loss.
|
|
Details: ...
|
|
Recommended action: ..."
|
|
```
|
|
|
|
**5. BURN orphans:**
|
|
```bash
|
|
# For empty wisps, etc.
|
|
rm .beads-wisp/<wisp-file>
|
|
```
|
|
|
|
**Exit criteria:** All orphans handled."""
|
|
|
|
[[steps]]
|
|
id = "report-findings"
|
|
title = "Generate and send orphan report"
|
|
needs = ["execute-recovery"]
|
|
description = """
|
|
Create summary report of orphan scan and actions.
|
|
|
|
**1. Generate report:**
|
|
```markdown
|
|
## Orphan Scan Report: {{timestamp}}
|
|
|
|
**Scope**: {{scope}}
|
|
**Orphans found**: {{total_count}}
|
|
|
|
### By Type
|
|
- Issues: {{issue_count}}
|
|
- Molecules: {{mol_count}}
|
|
- Wisps: {{wisp_count}}
|
|
|
|
### Actions Taken
|
|
- Reset to open: {{reset_count}}
|
|
- Reassigned: {{reassign_count}}
|
|
- Recovered: {{recover_count}}
|
|
- Escalated: {{escalate_count}}
|
|
- Burned: {{burn_count}}
|
|
|
|
### Details
|
|
{{#each orphan}}
|
|
- {{type}} {{id}}: {{action}} - {{reason}}
|
|
{{/each}}
|
|
```
|
|
|
|
**2. Send to Deacon (for logs):**
|
|
```bash
|
|
gt mail send deacon/ -s "Orphan scan complete: {{total_count}} found" \
|
|
-m "{{report}}"
|
|
```
|
|
|
|
**3. Send to Mayor (if escalations):**
|
|
```bash
|
|
# Only if there were escalations
|
|
gt mail send mayor/ -s "Orphan scan: {{escalate_count}} escalations" \
|
|
-m "{{escalations_section}}"
|
|
```
|
|
|
|
**Exit criteria:** Reports sent."""
|
|
|
|
[[steps]]
|
|
id = "return-to-kennel"
|
|
title = "Signal completion and return to kennel"
|
|
needs = ["report-findings"]
|
|
description = """
|
|
Signal work complete and return to available pool.
|
|
|
|
**1. Signal completion to Deacon:**
|
|
```bash
|
|
gt mail send deacon/ -s "DOG_DONE $(hostname)" -m "Task: orphan-scan
|
|
Scope: {{scope}}
|
|
Orphans found: {{total_count}}
|
|
Actions taken: {{action_summary}}
|
|
Status: COMPLETE
|
|
|
|
Ready for next assignment."
|
|
```
|
|
|
|
**2. Return to kennel:**
|
|
Dog returns to available state in the pool.
|
|
|
|
**Exit criteria:** Deacon notified, dog ready for next work."""
|
|
|
|
[vars]
|
|
[vars.scope]
|
|
description = "Scan scope: 'town' or specific rig name"
|
|
required = true
|
|
default = "town"
|