Files
gastown/.beads/formulas/mol-orphan-scan.formula.toml
max 37ae702427 docs: Clarify formula vs molecule semantics - formulas are NOT instructions
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>
2026-01-02 17:26:08 -08:00

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"