Files
gastown/internal/formula/formulas/mol-town-shutdown.formula.toml
gastown/crew/george ac63b10aa8 feat(formula): update mol-town-shutdown to v3 with full cleanup (gt-ux23f)
Added steps from discovered cleanup operations:
- clear-hooks: Detach all hooked work from agents
- reset-in-progress: Reset in-progress beads to open status
- burn-wisps: Clean up wisp directories and ephemeral beads
- validate-clean: Verify all cleanup operations succeeded

Updated existing steps with more detailed procedures.

Key principles preserved:
- No forcing, no lost work
- Idempotent (safe to run multiple times)
- Crew workers NOT affected (user-managed)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 13:19:00 -08:00

307 lines
6.6 KiB
TOML

description = """
Full Gas Town shutdown with cleanup.
This molecule provides a clean shutdown that:
- Preserves work (no forcing, no lost work)
- Cleans ephemeral state (wisps, stale beads)
- Resets agents to clean state
- Is idempotent (safe to run multiple times)
Use when you need to:
- Reset all state for a fresh start
- Recover from corrupted agent state
- Prepare for maintenance or upgrades
Sling to Mayor when ready to reboot:
gt sling mol-town-shutdown mayor
"""
formula = "mol-town-shutdown"
type = "workflow"
version = 3
[[steps]]
id = "preflight-check"
title = "Preflight safety check"
description = """
Scan for conditions that might make shutdown inadvisable.
```bash
gt shutdown preflight
```
This checks for:
- **Uncommitted changes**: Polecats with dirty git status
- **Unpushed commits**: Work that hasn't reached remote
- **Active merges**: Refinery mid-merge (could corrupt state)
- **Hooked work**: Agents with work still attached
- **In-progress beads**: Work that hasn't completed
Output is a report with warnings/blockers:
| Severity | Condition | Action |
|----------|-----------|--------|
| BLOCKER | Active merge in progress | Abort shutdown |
| WARNING | Uncommitted polecat changes | List affected polecats |
| WARNING | Unpushed commits | List repos needing push |
| WARNING | Hooked work | List agents with hooks |
| INFO | In-progress beads | Will be reset to open |
If blockers exist, STOP and resolve them first.
If only warnings, decide whether to proceed (work will be preserved).
"""
[[steps]]
id = "stop-sessions"
title = "Stop Claude sessions (preserve sandboxes)"
needs = ["preflight-check"]
description = """
Kill Claude processes but leave polecat sandboxes intact.
```bash
# Stop all polecat Claude sessions
gt stop --all --preserve-sandbox
# Verify sandboxes still exist
gt polecats --all --status
```
What this does:
- Kills tmux sessions running Claude
- Leaves git clones untouched
- Leaves hook files (pinned molecules) intact
- Leaves uncommitted work in place
What this does NOT do:
- Delete polecat directories
- Remove hook attachments
- Lose any git state
Note: Crew workers are NOT stopped (they're user-managed).
"""
[[steps]]
id = "clear-hooks"
title = "Clear agent hooks"
needs = ["stop-sessions"]
description = """
Detach all hooked work from agents.
```bash
# Clear hooks for all agents
for rig in $(gt rig list --names); do
gt unsling $rig/witness
gt unsling $rig/refinery
for polecat in $(gt polecat list $rig --names); do
gt unsling $rig/polecats/$polecat
done
done
# Clear deacon hook
gt unsling deacon
```
This ensures no agent will auto-start work on restart.
The beads themselves are preserved - just detached from hooks.
"""
[[steps]]
id = "reset-in-progress"
title = "Reset in-progress beads to open"
needs = ["clear-hooks"]
description = """
Reset beads that were in-progress to open status.
```bash
# Find all in-progress beads and reset
bd list --status=in_progress --format=ids | while read id; do
bd update $id --status=open --assignee=""
done
```
This ensures:
- No beads stuck in limbo after restart
- Work can be re-assigned fresh
- No orphaned assignments
"""
[[steps]]
id = "clear-inboxes"
title = "Archive and clear inboxes"
needs = ["reset-in-progress"]
description = """
Archive and clear all agent inboxes across all rigs.
```bash
# For each rig
for rig in $(gt rig list --names); do
gt mail clear $rig/witness --archive
gt mail clear $rig/refinery --archive
done
# Clear Mayor inbox
gt mail clear mayor --archive
# Clear Deacon inbox
gt mail clear deacon --archive
```
Messages are archived to `.beads/mail-archive/` before deletion.
Crew inboxes are NOT cleared (user manages those).
"""
[[steps]]
id = "burn-wisps"
title = "Clean up ephemeral data"
needs = ["clear-inboxes"]
description = """
Remove wisp directories and ephemeral beads.
```bash
# Remove wisp directories
for rig in $(gt rig list --paths); do
rm -rf $rig/.beads-wisp/
done
# Delete wisp beads from issues (hq-wisp-*, gt-wisp-*, etc.)
bd list --type=wisp --format=ids | while read id; do
bd delete $id --force
done
# Delete stale hooked handoff beads (more than 7 days old)
bd cleanup --stale-handoffs --age=7d
```
This prevents unbounded accumulation of ephemeral state.
"""
[[steps]]
id = "stop-daemon"
title = "Stop the daemon"
needs = ["burn-wisps"]
description = """
Stop the Gas Town daemon gracefully.
```bash
gt daemon stop
```
The daemon handles:
- Heartbeat monitoring
- Pending spawn triggers
- Background coordination
It will be restarted in the final step.
"""
[[steps]]
id = "rotate-logs"
title = "Rotate and archive logs"
needs = ["stop-daemon"]
description = """
Rotate logs to prevent unbounded growth.
```bash
# Rotate daemon logs
gt daemon rotate-logs
# Clean up old session captures
gt doctor --fix
```
Old logs are moved to `~/gt/logs/archive/` with timestamps.
"""
[[steps]]
id = "sync-state"
title = "Sync beads and push"
needs = ["rotate-logs"]
description = """
Ensure all beads state is persisted.
```bash
# Sync all rig beads
for rig in $(gt rig list --paths); do
(cd $rig && bd sync)
done
# Sync town beads
bd sync
```
Note: We do NOT force-commit polecat work here. Their sandboxes
are preserved with whatever state they had. They'll commit their
own work when they resume.
"""
[[steps]]
id = "validate-clean"
title = "Validate clean state"
needs = ["sync-state"]
description = """
Verify all cleanup operations succeeded.
```bash
gt shutdown validate
```
Checks:
- [ ] All inboxes empty (except crew)
- [ ] No hooked work
- [ ] No in-progress beads
- [ ] Beads synced
- [ ] No wisp directories
- [ ] Daemon stopped
Reports any discrepancies. Non-blocking - shutdown continues
but issues are logged for manual review.
"""
[[steps]]
id = "handoff-mayor"
title = "Send Mayor handoff"
needs = ["validate-clean"]
description = """
Record shutdown context for the fresh Mayor session.
```bash
gt mail send mayor -s "🤝 HANDOFF: Town shutdown complete" -m "
Town shutdown completed. State preserved.
Polecat sandboxes: PRESERVED (will resume from hooks)
Inboxes: ARCHIVED and cleared
Hooks: CLEARED
In-progress beads: RESET to open
Wisps: BURNED
Daemon: STOPPED
Next steps:
1. gt daemon start
2. gt prime
3. gt status (verify health)
4. Resume operations or respawn polecats
Shutdown reason: {{shutdown_reason}}
"
```
"""
[[steps]]
id = "restart-daemon"
title = "Restart daemon"
needs = ["handoff-mayor"]
description = """
Start the daemon with fresh state.
```bash
gt daemon start
```
The daemon will:
- Begin heartbeat monitoring
- Watch for pending spawns
- Resume background coordination
Polecats are NOT auto-respawned. Use `gt sling` or let Witness
restart them based on available work.
"""