Files
gastown/docs/deacon-plugins.md
Steve Yegge 0ad427e4a8 feat: Remove gt spawn completely - gt sling is THE command (gt-1py3y)
Fully remove gt spawn from the codebase:

- Delete spawn.go, create polecat_spawn.go with just sling helpers
- Remove all gt spawn references from docs and CLAUDE.md
- Update code comments to reference gt sling

gt sling now handles ALL work dispatch:
- Existing agents: gt sling <bead> mayor/crew/witness
- Auto-spawn: gt sling <bead> <rig>
- No-tmux: gt sling <bead> <rig> --naked
- With args: gt sling <bead> --args "..."

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 18:36:03 -08:00

6.5 KiB

Deacon Plugins

Town-level plugins that run during the Deacon's patrol loop.

Overview

The Deacon's patrol includes a plugin-run step. Rather than hardcoding what runs, we use directory-based discovery at ~/gt/plugins/. Each plugin directory contains enough information for the Deacon to decide whether to run it and what to do.

Plugins are not pre-validated by tooling. The Deacon reads each plugin's metadata and instructions, decides if the gate is open, and executes accordingly.

Directory Structure

~/gt/plugins/
├── beads-cleanup/
│   ├── plugin.md         # Gate info + instructions (combined)
│   └── state.json        # Auto-managed runtime state
├── health-report/
│   ├── plugin.md
│   └── state.json
└── wisp-pressure/
    ├── plugin.md
    └── state.json

Each plugin is a directory. If the directory exists, the plugin exists.

Plugin Metadata (plugin.md)

The plugin.md file contains YAML frontmatter for gate configuration, followed by markdown instructions for the Deacon.

---
gate: cooldown
interval: 24h
parallel: true
---

# Beads Cleanup

Clean up old wisps daily.

## Actions

1. Run `bd cleanup --wisp --force`
2. Run `bd doctor` to verify health
3. Log summary of cleaned items

Frontmatter Fields

Field Required Description
gate Yes Gate type: cooldown, cron, condition, event
interval For cooldown Duration: 1h, 24h, 5m, etc.
schedule For cron Cron expression: 0 9 * * *
check For condition Command that outputs a number
operator For condition Comparison: gt, lt, eq, ge, le
threshold For condition Numeric threshold
trigger For event Event name: startup, heartbeat
cooldown Optional Min time between runs (for condition gates)
parallel Optional If true, can run concurrently with other plugins

Gate Types

Cooldown

Run at most once per interval since last successful run.

---
gate: cooldown
interval: 24h
---

Cron

Run on a schedule (standard cron syntax).

---
gate: cron
schedule: "0 9 * * *"   # 9am daily
---

Condition

Run when a command's output crosses a threshold.

---
gate: condition
check: "bd count --type=wisp"
operator: gt
threshold: 50
cooldown: 30m           # Don't spam even if condition stays true
---

The check command must output a single number. The Deacon compares it against threshold using operator.

Event

Run in response to specific events.

---
gate: event
trigger: startup        # Run once when daemon starts
---

Triggers: startup, heartbeat (every patrol), mail (when inbox has items).

State Management

The Deacon maintains state.json in each plugin directory:

{
  "lastRun": "2025-12-21T10:00:00Z",
  "lastResult": "success",
  "runCount": 42,
  "nextEligible": "2025-12-22T10:00:00Z"
}

This is auto-managed. Plugins don't need to touch it.

Parallel Execution

Plugins marked parallel: true can run concurrently. During plugin-run, the Deacon:

  1. Scans ~/gt/plugins/ for plugins with open gates
  2. Groups them: parallel vs sequential
  3. Launches parallel plugins using Task tool subagents
  4. Runs sequential plugins one at a time
  5. Waits for all to complete before continuing patrol

Sequential plugins (default) run in directory order. Use sequential for plugins that modify shared state or have ordering dependencies.

Example Plugins

beads-cleanup (daily maintenance)

---
gate: cooldown
interval: 24h
parallel: true
---

# Beads Cleanup

Daily cleanup of wisp storage.

## Actions

1. Run `bd cleanup --wisp --force` to remove old wisps
2. Run `bd doctor` to check for issues
3. Report count of cleaned items

wisp-pressure (condition-triggered)

---
gate: condition
check: "bd count --type=wisp"
operator: gt
threshold: 100
cooldown: 1h
parallel: true
---

# Wisp Pressure Relief

Triggered when wisp count gets too high.

## Actions

1. Run `bd cleanup --wisp --age=4h` (remove wisps > 4h old)
2. Check `bd count --type=wisp`
3. If still > 50, run `bd cleanup --wisp --age=1h`
4. Report final count

health-report (scheduled)

---
gate: cron
schedule: "0 9 * * *"
parallel: false
---

# Morning Health Report

Generate daily health summary for the overseer.

## Actions

1. Run `gt status` to get overall health
2. Run `bd stats` to get metrics
3. Check for stale agents (no heartbeat > 1h)
4. Send summary: `gt mail send --human -s "Morning Report" -m "..."`

startup-check (event-triggered)

---
gate: event
trigger: startup
parallel: false
---

# Startup Verification

Run once when the daemon starts.

## Actions

1. Verify `gt doctor` passes
2. Check all rigs have healthy Witnesses
3. Report any issues to Mayor inbox

Patrol Integration

The mol-deacon-patrol step 3 (plugin-run) works as follows:

## Step: plugin-run

Execute registered plugins whose gates are open.

1. Scan `~/gt/plugins/` for plugin directories
2. For each plugin, read `plugin.md` frontmatter
3. Check if gate is open (based on type and state.json)
4. Collect eligible plugins into parallel and sequential groups

5. For parallel plugins:
   - Use Task tool to spawn subagents for each
   - Each subagent reads the plugin's instructions and executes
   - Wait for all to complete

6. For sequential plugins:
   - Execute each in order
   - Read instructions, run actions, update state

7. Update state.json for each completed plugin
8. Log summary: "Ran N plugins (M parallel, K sequential)"

Limitations

  • No polecat spawning: Plugins cannot spawn polecats. If a plugin tries to use gt sling, behavior is undefined. This may change in the future.

  • No cross-plugin dependencies: Plugins don't declare dependencies on each other. If ordering matters, mark both as parallel: false.

  • No plugin-specific state API: Plugins can write to their own directory if needed, but there's no structured API for plugin state beyond what the Deacon auto-manages.

CLI Commands (Future)

gt plugins list              # Show all plugins, gates, status
gt plugins check             # Show plugins with open gates
gt plugins show <name>       # Detail view of one plugin
gt plugins run <name>        # Force-run (ignore gate)

These commands are not yet implemented. The Deacon reads the directory structure directly during patrol.