From c6a9201b5e2a394c975035286bcb93603da80cf9 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Tue, 30 Dec 2025 10:35:53 -0800 Subject: [PATCH] Add infrastructure formulas for dog tasks (gt-0x5og.5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create five formulas for dog-executed infrastructure tasks: - mol-convoy-cleanup: Archive convoy, notify overseer - mol-dep-propagate: Cross-rig dependency resolution - mol-digest-generate: Daily digest for overseer - mol-orphan-scan: Find and reassign orphaned work - mol-session-gc: Clean stale sessions Each formula follows the standard TOML structure with: - Description and dog contract - Step-by-step workflow with dependencies - Variable definitions - Squash configuration for digests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../formulas/mol-convoy-cleanup.formula.toml | 209 ++++++++++++ .../formulas/mol-dep-propagate.formula.toml | 208 ++++++++++++ .../formulas/mol-digest-generate.formula.toml | 227 +++++++++++++ .beads/formulas/mol-orphan-scan.formula.toml | 312 ++++++++++++++++++ .beads/formulas/mol-session-gc.formula.toml | 250 ++++++++++++++ 5 files changed, 1206 insertions(+) create mode 100644 .beads/formulas/mol-convoy-cleanup.formula.toml create mode 100644 .beads/formulas/mol-dep-propagate.formula.toml create mode 100644 .beads/formulas/mol-digest-generate.formula.toml create mode 100644 .beads/formulas/mol-orphan-scan.formula.toml create mode 100644 .beads/formulas/mol-session-gc.formula.toml diff --git a/.beads/formulas/mol-convoy-cleanup.formula.toml b/.beads/formulas/mol-convoy-cleanup.formula.toml new file mode 100644 index 00000000..5692196e --- /dev/null +++ b/.beads/formulas/mol-convoy-cleanup.formula.toml @@ -0,0 +1,209 @@ +description = """ +Archive completed convoys and notify overseer. + +Dogs execute this formula when convoys complete. The Deacon detects completed +convoys (all tracked issues closed) and slings this work to a dog for: +- Generating convoy summary +- Archiving convoy state +- Notifying the overseer (Mayor) +- Updating activity feed + +## Dog Contract + +This is infrastructure work. You: +1. Receive convoy ID via hook_bead +2. Generate summary of completed work +3. Archive to appropriate location +4. Notify stakeholders +5. Return to kennel + +## Variables + +| Variable | Source | Description | +|----------|--------|-------------| +| convoy | hook_bead | The convoy ID to archive | + +## Failure Modes + +| Situation | Action | +|-----------|--------| +| Convoy not found | Exit with error, notify Deacon | +| Archive location full | Create space, retry, or escalate | +| Mail send fails | Retry once, then proceed anyway |""" +formula = "mol-convoy-cleanup" +version = 1 + +[squash] +trigger = "on_complete" +template_type = "work" +include_metrics = true + +[[steps]] +id = "load-convoy" +title = "Load convoy and verify completion" +description = """ +Load the convoy bead and verify it's ready for archival. + +**1. Check your assignment:** +```bash +gt mol status # Shows hook_bead = convoy ID +bd show {{convoy}} # Full convoy details +``` + +**2. Verify convoy is complete:** +- Status should be 'closed' or all tracked issues closed +- If convoy is still open, exit - Deacon dispatched too early + +```bash +bd show {{convoy}} +# Check 'tracks' or 'dependencies' field +# All tracked issues should be closed +``` + +**3. Gather convoy metadata:** +- Start date (created_at) +- End date (last closure timestamp) +- Total issues tracked +- Contributing polecats + +**Exit criteria:** Convoy loaded, verified complete, metadata gathered.""" + +[[steps]] +id = "generate-summary" +title = "Generate convoy summary" +needs = ["load-convoy"] +description = """ +Create a summary of the convoy's completed work. + +**1. Collect tracked issue details:** +```bash +# For each tracked issue +bd show +# Extract: title, type, assignee, duration +``` + +**2. Calculate statistics:** +- Total duration (convoy start to finish) +- Issues by type (task, bug, feature) +- Contributors (unique assignees) +- Commits generated (if tracked) + +**3. Create summary text:** +```markdown +## Convoy Summary: {{convoy.title}} + +**Duration**: X days/hours +**Issues completed**: N + +### Work Breakdown +- Tasks: N +- Bugs: N +- Features: N + +### Contributors +- polecat-1: N issues +- polecat-2: N issues + +### Key Outcomes +- +- +``` + +**Exit criteria:** Summary text generated and ready for notification.""" + +[[steps]] +id = "archive-convoy" +title = "Archive convoy to cold storage" +needs = ["generate-summary"] +description = """ +Move convoy from active to archived state. + +**1. Update convoy status:** +```bash +bd update {{convoy}} --status=archived +# Or close if not already closed +bd close {{convoy}} --reason="Convoy complete, archived" +``` + +**2. Generate archive record:** +The convoy bead with all metadata is the archive record. Beads retention +handles moving it to `.beads/archive/` after the retention period. + +**3. Verify archive:** +```bash +bd show {{convoy}} +# Status should reflect archived state +``` + +**4. Sync to persist:** +```bash +bd sync +``` + +**Exit criteria:** Convoy archived, changes synced.""" + +[[steps]] +id = "notify-overseer" +title = "Send completion notification to overseer" +needs = ["archive-convoy"] +description = """ +Notify the Mayor (overseer) of convoy completion. + +**1. Send completion mail:** +```bash +gt mail send mayor/ -s "Convoy complete: {{convoy.title}}" -m "$(cat < +# Check if this was the only blocker +``` + +**2. Check if now unblocked:** +```bash +bd blocked +# If empty or only shows other blockers, issue is now unblocked +``` + +**3. Verify automatic unblock worked:** +Beads should auto-update blocked status when dependencies close. +This step verifies and fixes if needed: +```bash +# If still showing as blocked by resolved issue (shouldn't happen): +bd dep remove {{resolved_issue}} +``` + +**Exit criteria:** All cross-rig dependents have updated blocked status.""" + +[[steps]] +id = "notify-witnesses" +title = "Notify affected rig Witnesses" +needs = ["update-blocked-status"] +description = """ +Send notifications to Witnesses of affected rigs. + +**1. Group dependents by rig:** +- gastown/witness: for gt-* issues +- beads/witness: for bd-* issues +- etc. + +**2. For each affected rig, send notification:** +```bash +gt mail send /witness -s "Dependency resolved: {{resolved_issue}}" -m "$(cat < +# Check: +# - Status: should be 'open' (not already in_progress) +# - Priority: high priority may warrant immediate dispatch +# - No other blockers: bd blocked should be empty +``` + +**2. Decision: trigger dispatch?** + +| Condition | Action | +|-----------|--------| +| High priority (P0-P1) + open + unblocked | Recommend immediate dispatch | +| Medium priority (P2) + open + unblocked | Note in Witness notification | +| Low priority (P3-P4) | Let Witness handle in next patrol | + +**3. If triggering dispatch:** +```bash +# For high priority, suggest to Mayor: +gt mail send mayor/ -s "High-priority work unblocked: " -m "..." +``` + +Usually, the Witness notification (previous step) is sufficient - Witnesses +handle their own dispatch decisions. + +**Exit criteria:** Dispatch recommendations sent where appropriate.""" + +[[steps]] +id = "return-to-kennel" +title = "Signal completion and return to kennel" +needs = ["trigger-dispatch"] +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: dep-propagate +Resolved: {{resolved_issue}} +Cross-rig dependents: {{dependent_count}} +Witnesses notified: {{witness_list}} +Status: COMPLETE + +Ready for next assignment." +``` + +**2. Update activity feed:** +The propagation creates implicit feed entries (dependency updates). +No explicit entry needed. + +**3. Return to kennel:** +Dog returns to available state in the pool. + +**Exit criteria:** Deacon notified, dog ready for next work or retirement.""" + +[vars] +[vars.resolved_issue] +description = "The issue ID that just closed and needs propagation" +required = true diff --git a/.beads/formulas/mol-digest-generate.formula.toml b/.beads/formulas/mol-digest-generate.formula.toml new file mode 100644 index 00000000..07337ce3 --- /dev/null +++ b/.beads/formulas/mol-digest-generate.formula.toml @@ -0,0 +1,227 @@ +description = """ +Generate daily digest for overseer (Mayor). + +Dogs execute this formula on a scheduled basis (daily, or triggered by plugin) +to create summary digests of Gas Town activity. This aggregates: +- Work completed across all rigs +- Issues filed and closed +- Incidents and escalations +- Agent health metrics +- Key statistics and trends + +## Dog Contract + +This is infrastructure work. You: +1. Receive digest period via hook_bead (e.g., daily, weekly) +2. Collect data from all rigs you have access to +3. Generate formatted digest +4. Send to overseer +5. Archive digest as bead +6. Return to kennel + +## Variables + +| Variable | Source | Description | +|----------|--------|-------------| +| period | hook_bead | Time period for digest (daily, weekly) | +| since | computed | Start timestamp for data collection | +| until | computed | End timestamp (usually now) | + +## Why Dogs? + +Digest generation requires reading from multiple rigs. Dogs have multi-rig +worktrees. This is also a periodic task that doesn't need a dedicated polecat.""" +formula = "mol-digest-generate" +version = 1 + +[squash] +trigger = "on_complete" +template_type = "work" +include_metrics = true + +[[steps]] +id = "determine-period" +title = "Determine digest time period" +description = """ +Establish the time range for this digest. + +**1. Check assignment:** +```bash +gt mol status # Shows period type +``` + +**2. Calculate time range:** + +| Period | Since | Until | +|--------|-------|-------| +| daily | Yesterday 00:00 | Today 00:00 | +| weekly | Last Monday 00:00 | This Monday 00:00 | +| custom | From hook_bead | From hook_bead | + +```bash +# For daily digest +since=$(date -v-1d +%Y-%m-%dT00:00:00) +until=$(date +%Y-%m-%dT00:00:00) +``` + +**3. Record period for reporting:** +Note the exact timestamps for the digest header. + +**Exit criteria:** Time period established with precise timestamps.""" + +[[steps]] +id = "collect-rig-data" +title = "Collect activity data from all rigs" +needs = ["determine-period"] +description = """ +Gather activity data from each rig in the town. + +**1. List accessible rigs:** +```bash +gt rigs +# Returns list of rigs: gastown, beads, etc. +``` + +**2. For each rig, collect:** + +a) **Issues filed and closed:** +```bash +# From rig beads +bd list --created-after={{since}} --created-before={{until}} +bd list --status=closed --updated-after={{since}} +``` + +b) **Agent activity:** +```bash +gt polecats # Polecat activity +gt feed --since={{since}} # Activity feed entries +``` + +c) **Merges:** +```bash +# Git log for merges to main +git -C log --merges --since={{since}} --oneline main +``` + +d) **Incidents:** +```bash +# Issues tagged as incident or high-priority +bd list --label=incident --created-after={{since}} +``` + +**3. Aggregate across rigs:** +Sum counts, collect notable items, identify trends. + +**Exit criteria:** Raw data collected from all accessible rigs.""" + +[[steps]] +id = "generate-digest" +title = "Generate formatted digest" +needs = ["collect-rig-data"] +description = """ +Transform collected data into formatted digest. + +**1. Calculate summary statistics:** +- Total issues filed +- Total issues closed +- Net change (closed - filed) +- By type (task, bug, feature) +- By rig + +**2. Identify highlights:** +- Biggest completions (epics, large features) +- Incidents (any P0/P1 issues) +- Notable trends (increasing backlog, fast closure rate) + +**3. Generate digest text:** +```markdown +# Gas Town Daily Digest: {{date}} + +## Summary +- **Issues filed**: N (tasks: X, bugs: Y, features: Z) +- **Issues closed**: N +- **Net change**: +/-N + +## By Rig +| Rig | Filed | Closed | Active Polecats | +|-----|-------|--------|-----------------| +| gastown | X | Y | Z | +| beads | X | Y | Z | + +## Highlights +### Completed +- {{epic or feature}} - completed by {{polecat}} + +### Incidents +- {{incident summary if any}} + +## Agent Health +- Polecats spawned: N +- Polecats retired: N +- Average work duration: Xh + +## Trends +- Backlog: {{increasing/stable/decreasing}} +- Throughput: {{issues/day}} +``` + +**Exit criteria:** Formatted digest ready for delivery.""" + +[[steps]] +id = "send-digest" +title = "Send digest to overseer" +needs = ["generate-digest"] +description = """ +Deliver digest to the Mayor. + +**1. Send via mail:** +```bash +gt mail send mayor/ -s "Gas Town Digest: {{date}}" -m "$(cat <': 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 +# Get assignee field +``` + +**3. Check if assignee session exists:** +```bash +# If assignee is a polecat +gt polecats # Is the polecat active? +tmux has-session -t 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 +# Get agent/session info +``` + +**3. Check if owner session exists:** +```bash +tmux has-session -t 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 +git log --oneline +``` + +**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 --status=open --assignee="" +# Clears in_progress, ready for dispatch +``` + +**2. REASSIGN orphans:** +```bash +# Notify Witness to handle assignment +gt mail send /witness -s "Orphan needs assignment: " \ + -m "Issue 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 --status=open \ + --note="Recovery: work exists on branch " +``` + +**4. ESCALATE orphans:** +```bash +gt mail send mayor/ -s "Orphan requires escalation: " \ + -m "Issue orphaned with possible data loss. +Details: ... +Recommended action: ..." +``` + +**5. BURN orphans:** +```bash +# For empty wisps, etc. +rm .beads-wisp/ +``` + +**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" diff --git a/.beads/formulas/mol-session-gc.formula.toml b/.beads/formulas/mol-session-gc.formula.toml new file mode 100644 index 00000000..e53ae1dd --- /dev/null +++ b/.beads/formulas/mol-session-gc.formula.toml @@ -0,0 +1,250 @@ +description = """ +Clean stale sessions and garbage collect. + +Dogs execute this formula to clean up dead sessions, orphaned processes, and +other system cruft. This is the garbage collector for Gas Town's runtime: +- Dead tmux sessions (no Claude process) +- Orphaned Claude processes (no tmux parent) +- Stale wisps past retention +- Leftover state files + +## Dog Contract + +This is infrastructure work. You: +1. Receive gc scope via hook_bead (aggressive or conservative) +2. Identify garbage across the system +3. Safely remove dead state +4. Report what was cleaned +5. Return to kennel + +## Variables + +| Variable | Source | Description | +|----------|--------|-------------| +| mode | hook_bead | GC mode: 'conservative' (safe) or 'aggressive' (thorough) | + +## Safety + +GC is destructive. This formula errs on the side of caution: +- Conservative mode: Only obviously dead things +- Aggressive mode: Includes old but possibly-recoverable state + +Running `gt doctor --fix` handles most of this. This formula wraps it with +reporting and multi-rig scope.""" +formula = "mol-session-gc" +version = 1 + +[squash] +trigger = "on_complete" +template_type = "work" +include_metrics = true + +[[steps]] +id = "determine-mode" +title = "Determine GC mode" +description = """ +Establish GC aggressiveness level. + +**1. Check assignment:** +```bash +gt mol status # Shows mode in hook_bead +``` + +**2. Mode definitions:** + +| Mode | Description | Risk | +|------|-------------|------| +| conservative | Only clearly dead state | Very low | +| aggressive | Includes stale state | Low but non-zero | + +**Conservative targets:** +- tmux sessions with no processes +- Claude processes with no tmux parent +- Wisps > 24 hours old + +**Aggressive additions:** +- Wisps > 1 hour old +- Branches with no matching polecat +- State files > 7 days old + +**Exit criteria:** GC mode determined.""" + +[[steps]] +id = "preview-cleanup" +title = "Preview what will be cleaned" +needs = ["determine-mode"] +description = """ +Identify garbage without removing it yet. + +**1. Run doctor in preview mode:** +```bash +gt doctor -v +# Shows what would be cleaned, doesn't do it +``` + +**2. Parse doctor output for:** +- orphan-sessions: Tmux sessions to kill +- orphan-processes: Claude processes to terminate +- wisp-gc: Wisps to delete + +**3. Additional scans (for aggressive mode):** +```bash +# Old branches +git branch --list 'polecat/*' | while read branch; do + last_commit=$(git log -1 --format=%ct "$branch") + # If > 7 days old and no matching polecat, candidate for cleanup +done + +# Old state files +find ~/.gt/ -name "*.state" -mtime +7 +``` + +**4. Compile cleanup manifest:** +Record each item to be cleaned with: +- Type (session, process, wisp, branch, state) +- Identifier +- Age +- Reason for cleanup + +**Exit criteria:** Cleanup manifest ready, nothing deleted yet.""" + +[[steps]] +id = "execute-gc" +title = "Execute garbage collection" +needs = ["preview-cleanup"] +description = """ +Actually remove the garbage. + +**1. Run doctor with fix:** +```bash +gt doctor --fix +# This handles sessions, processes, and wisps +``` + +**2. For aggressive mode, additional cleanup:** +```bash +# Old branches (if aggressive mode) +git branch -D + +# Old state files (if aggressive mode) +rm +``` + +**3. Track what was deleted:** +Record each item actually removed for the report. + +**Safety checks:** +- Never delete active sessions (tmux list-clients) +- Never delete branches with uncommitted polecat work +- Never delete wisps < 1 hour old + +**Exit criteria:** Garbage collected.""" + +[[steps]] +id = "verify-cleanup" +title = "Verify cleanup was successful" +needs = ["execute-gc"] +description = """ +Confirm garbage was actually removed. + +**1. Re-run doctor to verify:** +```bash +gt doctor -v +# Should show no issues (or fewer issues) +``` + +**2. Check for stragglers:** +```bash +# Tmux sessions +tmux list-sessions 2>/dev/null + +# Claude processes +pgrep -f claude + +# Wisps +ls .beads-wisp/ 2>/dev/null | wc -l +``` + +**3. Compare before/after:** +- Sessions before: N → after: M +- Processes before: N → after: M +- Wisps before: N → after: M + +**Exit criteria:** Cleanup verified.""" + +[[steps]] +id = "report-gc" +title = "Generate GC report" +needs = ["verify-cleanup"] +description = """ +Create summary report of garbage collection. + +**1. Generate report:** +```markdown +## Session GC Report: {{timestamp}} + +**Mode**: {{mode}} + +### Summary +| Type | Before | After | Cleaned | +|------|--------|-------|---------| +| Sessions | X | Y | Z | +| Processes | X | Y | Z | +| Wisps | X | Y | Z | +| Branches | X | Y | Z | +| State files | X | Y | Z | + +### Items Cleaned +{{#each cleaned}} +- {{type}}: {{identifier}} (age: {{age}}, reason: {{reason}}) +{{/each}} + +### Errors +{{#if errors}} +{{#each errors}} +- {{item}}: {{error}} +{{/each}} +{{else}} +None +{{/if}} + +### Space Recovered +~{{bytes_freed}} bytes +``` + +**2. Send to Deacon:** +```bash +gt mail send deacon/ -s "GC complete: {{total_cleaned}} items" \ + -m "{{report}}" +``` + +**Exit criteria:** Report sent.""" + +[[steps]] +id = "return-to-kennel" +title = "Signal completion and return to kennel" +needs = ["report-gc"] +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: session-gc +Mode: {{mode}} +Items cleaned: {{total_cleaned}} +Space recovered: {{bytes_freed}} +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.mode] +description = "GC mode: 'conservative' or 'aggressive'" +required = true +default = "conservative"