From fbb8b1f0404b38a2a137592fe95bf0e721490e57 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Mon, 15 Dec 2025 20:16:31 -0800 Subject: [PATCH] docs: add design docs for swarm shutdown, polecat beads, and mayor handoff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - swarm-shutdown-design.md: Worker cleanup, Witness verification, session cycling - polecat-beads-access-design.md: Per-rig beads config, worker prompting - mayor-handoff-design.md: Mayor session cycling and handoff protocol Closes design epics: gt-82y, gt-l3c, gt-u82 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- docs/mayor-handoff-design.md | 493 +++++++++++++++++++++++++ docs/polecat-beads-access-design.md | 448 ++++++++++++++++++++++ docs/swarm-shutdown-design.md | 554 ++++++++++++++++++++++++++++ 3 files changed, 1495 insertions(+) create mode 100644 docs/mayor-handoff-design.md create mode 100644 docs/polecat-beads-access-design.md create mode 100644 docs/swarm-shutdown-design.md diff --git a/docs/mayor-handoff-design.md b/docs/mayor-handoff-design.md new file mode 100644 index 00000000..7e4bf54a --- /dev/null +++ b/docs/mayor-handoff-design.md @@ -0,0 +1,493 @@ +# Mayor Session Cycling and Handoff Design + +Design for Mayor session management, context cycling, and structured handoff. + +**Epic**: gt-u82 (Design: Mayor session cycling and handoff) + +## Overview + +Mayor coordinates across all rigs and runs for extended periods. Like Witness, +Mayor needs to cycle sessions when context fills, producing structured handoff +notes for the next session. + +## Key Differences from Witness + +| Aspect | Witness | Mayor | +|--------|---------|-------| +| Scope | Single rig, workers | All rigs, refineries | +| State tracking | Worker status, pending verifications | Active swarms, rig status, escalations | +| Handoff recipient | Self (same rig Witness) | Self (Mayor) | +| Complexity | Medium | Higher (cross-rig coordination) | +| Daemon | Witness daemon respawns | No daemon (manual or cron restart) | + +## Design Areas + +1. **Session cycling recognition** - When Mayor should cycle +2. **Handoff note format** - Structured state capture +3. **Handoff delivery** - Mail to self +4. **Fresh session startup** - Reading and resuming from handoff +5. **Integration with town commands** - CLI support + +--- + +## 1. Session Cycling Recognition + +### When to Cycle + +Mayor should cycle when: +- Context is noticeably filling (responses slowing, losing track of state) +- Major phase completed (swarm finished, integration done) +- User requests session end +- Extended idle period with no active work + +### Proactive vs Reactive + +**Proactive** (preferred): +- Mayor notices context filling and initiates handoff +- Clean state capture while still coherent + +**Reactive** (fallback): +- Session times out or crashes +- Less clean, may lose state + +### Recognition Cues (for prompting) + +```markdown +## Session Cycling + +Monitor your context usage throughout the session. Signs you should cycle: + +- You've been running for several hours +- You're having trouble remembering earlier conversation context +- You've completed a major phase of work +- Responses are taking longer than usual +- You're about to start a complex new operation + +When you notice these signs, proactively initiate handoff rather than +waiting for problems. +``` + +--- + +## 2. Handoff Note Format + +### Structure + +Mayor handoff captures cross-rig state: + +``` +[HANDOFF_TYPE]: mayor_cycle +[TIMESTAMP]: 2024-01-15T14:30:00Z +[SESSION_DURATION]: 3h 45m + +## Active Swarms + + +## Rig Status + + +## Pending Escalations + + +## In-Flight Decisions + + +## Recent Actions + + +## Delegated Work + + +## User Requests + + +## Next Steps + + +## Warnings/Notes + +``` + +### Example Handoff Note + +```markdown +[HANDOFF_TYPE]: mayor_cycle +[TIMESTAMP]: 2024-01-15T14:30:00Z +[SESSION_DURATION]: 3h 45m + +## Active Swarms + +### gastown +- Status: Active swarm on auth feature +- Refinery: gastown/refinery coordinating +- Workers: 3 active (Furiosa, Toast, Capable) +- Issues: gt-auth-1, gt-auth-2, gt-auth-3 +- Expected completion: Soon (2/3 issues merged) + +### beads +- Status: Idle, no active swarm +- Last activity: 2h ago (maintenance work) + +## Rig Status + +| Rig | Health | Last Contact | Notes | +|-----|--------|--------------|-------| +| gastown | Good | 5min ago | Swarm active | +| beads | Good | 2h ago | Idle | + +## Pending Escalations + +1. **gastown/Toast stuck** - Witness escalated at 14:15 + - Issue: gt-auth-2 has merge conflict + - Awaiting decision: reassign or manual fix? + - Context: Toast tried 3 times, conflict in auth/middleware.go + +## In-Flight Decisions + +None currently. + +## Recent Actions + +1. 14:25 - Checked gastown swarm status +2. 14:20 - Received escalation re: Toast +3. 14:00 - Sent status request to beads/refinery +4. 13:30 - Dispatched auth swarm to gastown +5. 13:00 - Session started, read previous handoff + +## Delegated Work + +- gastown/refinery: Auth feature swarm (dispatched 13:30) + - Expecting completion report when done + +## User Requests + +- User asked for auth feature implementation (completed dispatch) +- No other pending requests + +## Next Steps + +1. **Resolve Toast escalation** - Decide on reassign vs manual fix +2. **Monitor gastown swarm** - Should complete soon +3. **Check beads rig** - Been quiet, verify health + +## Warnings/Notes + +- Toast merge conflict is blocking swarm completion +- Consider waking another polecat if reassignment needed +``` + +--- + +## 3. Handoff Delivery + +### Mail to Self + +Mayor mails handoff to own inbox: + +```bash +town mail send mayor/ -s "Session Handoff" -m "" +``` + +### Why Mail (not file)? + +- Consistent with Witness pattern +- Timestamped and logged +- Works across potential Mayor instances +- Integrates with existing inbox check on startup + +### Handoff Template Function + +```python +def mayor_handoff( + active_swarms: List[SwarmStatus], + rig_status: Dict[str, RigStatus], + pending_escalations: List[Escalation], + in_flight_decisions: List[Decision], + recent_actions: List[str], + delegated_work: List[DelegatedItem], + user_requests: List[str], + next_steps: List[str], + warnings: Optional[str] = None, + session_duration: Optional[str] = None, +) -> Message: + """Create Mayor session handoff note.""" + + metadata = { + "template": "MAYOR_HANDOFF", + "timestamp": datetime.utcnow().isoformat(), + "session_duration": session_duration, + "active_swarm_count": len(active_swarms), + "pending_escalation_count": len(pending_escalations), + } + + # ... format sections ... + + return Message.create( + sender="mayor/", + recipient="mayor/", + subject="Session Handoff", + body=body, + priority="high", # Ensure it's seen + ) +``` + +--- + +## 4. Fresh Session Startup + +### Startup Protocol + +When Mayor session starts: + +1. **Check for handoff**: +```bash +town inbox | grep "Session Handoff" +``` + +2. **If handoff exists**: +```bash +# Read most recent handoff +town read + +# Resume from handoff state +# - Address pending escalations first +# - Check on in-flight work +# - Continue with next steps +``` + +3. **If no handoff** (fresh start): +```bash +# Full system status check +town status +town rigs +bd ready + +# Check all rig inboxes for pending items +town inbox +``` + +### Handoff Processing + +```markdown +## On Session Start + +1. **Check inbox for handoff**: +```bash +town inbox +``` +Look for "Session Handoff" messages. + +2. **If handoff found**: + - Read the handoff note + - Process pending escalations (highest priority) + - Check status of noted swarms + - Verify rig health matches notes + - Continue with documented next steps + +3. **If no handoff**: + - Do full status check: `town status` + - Check each rig: `town rigs` + - Check inbox for any messages + - Check beads for work: `bd ready` + +4. **After processing handoff**: + - Archive or delete the handoff message + - You now own the current state +``` + +--- + +## 5. Integration with Town Commands + +### New Commands (optional, can be deferred) + +```bash +# Generate handoff note interactively +town handoff + +# Generate and send in one step +town handoff --send + +# Check for handoff on startup +town resume +``` + +### Implementation + +For now, Mayor does this manually in prompting. Later can add CLI support: + +```go +// cmd/gt/cmd/handoff.go +var handoffCmd = &cobra.Command{ + Use: "handoff", + Short: "Generate session handoff note", + Run: func(cmd *cobra.Command, args []string) { + // Gather state + swarms := gatherActiveSwarms() + rigs := gatherRigStatus() + // ... etc + + // Format handoff + note := formatHandoffNote(swarms, rigs, ...) + + if send { + // Send to mayor inbox + mail.Send("mayor/", "Session Handoff", note) + } else { + // Print for review + fmt.Println(note) + } + }, +} +``` + +--- + +## Subtasks + +Based on this design, create these implementation subtasks: + +### gt-u82.1: Mayor session cycling prompting + +Add to Mayor CLAUDE.md: +- When to cycle recognition +- How to compose handoff note +- Handoff format specification + +### gt-u82.2: Mayor startup protocol prompting + +Add to Mayor CLAUDE.md: +- Check for handoff on start +- Process handoff content +- Fresh start fallback + +### gt-u82.3: Mayor handoff mail template + +Add to templates.py: +- MAYOR_HANDOFF template +- Parsing utilities + +### gt-u82.4: (Optional) town handoff command + +CLI support for handoff generation: +- `town handoff` - generate interactively +- `town handoff --send` - generate and mail +- `town resume` - check for and display handoff + +--- + +## Prompting Additions + +### Mayor CLAUDE.md - Session Management Section + +```markdown +## Session Management + +### Recognizing When to Cycle + +Monitor your session health. Cycle proactively when: +- You've been running for several hours +- Context feels crowded (losing track of earlier state) +- Major phase completed (good stopping point) +- About to start complex new work + +Don't wait for problems - proactive handoff produces cleaner state. + +### Creating Handoff Notes + +Before ending your session, capture current state: + +1. **Gather information**: +```bash +town status # Overall health +town rigs # Each rig's state +town inbox # Pending messages +bd ready # Work items +``` + +2. **Compose handoff note** with this structure: + +``` +[HANDOFF_TYPE]: mayor_cycle +[TIMESTAMP]: +[SESSION_DURATION]: + +## Active Swarms + + +## Rig Status + + +## Pending Escalations + + +## In-Flight Decisions + + +## Recent Actions + + +## Delegated Work + + +## User Requests + + +## Next Steps + + +## Warnings/Notes + +``` + +3. **Send handoff**: +```bash +town mail send mayor/ -s "Session Handoff" -m "" +``` + +4. **End session** - next instance will pick up from handoff. + +### On Session Start + +1. **Check for handoff**: +```bash +town inbox | grep "Session Handoff" +``` + +2. **If found, read it**: +```bash +town read +``` + +3. **Process in priority order**: + - Pending escalations (urgent) + - In-flight decisions (context-dependent) + - Check noted swarm status (may have changed) + - Continue with next steps + +4. **If no handoff**: +```bash +town status +town rigs +bd ready +town inbox +``` + Build your own picture of current state. + +### Handoff Best Practices + +- **Be specific** - "Toast has merge conflict in auth/middleware.go" not "Toast is stuck" +- **Include context** - Why decisions are pending, what you were thinking +- **Prioritize next steps** - What's most urgent +- **Note time-sensitive items** - Anything that might have changed since handoff +``` + +--- + +## Implementation Checklist + +- [ ] Create subtasks (gt-u82.1 through gt-u82.4) +- [ ] Add session management section to Mayor CLAUDE.md template +- [ ] Add MAYOR_HANDOFF template to templates.py +- [ ] Update startup instructions in Mayor prompting +- [ ] (Optional) Implement town handoff command diff --git a/docs/polecat-beads-access-design.md b/docs/polecat-beads-access-design.md new file mode 100644 index 00000000..0084c1f8 --- /dev/null +++ b/docs/polecat-beads-access-design.md @@ -0,0 +1,448 @@ +# Polecat Beads Write Access Design + +Design for granting polecats direct beads write access. + +**Epic**: gt-l3c (Design: Polecat Beads write access) + +## Background + +Originally, polecats were read-only for beads to prevent multi-agent conflicts. +With Beads v0.30.0's tombstone-based rearchitecture for deletions, we now have +solid multi-agent support even at high concurrent load. + +## Benefits + +1. **Simplifies architecture** - No need for mail-based issue filing proxy via Witness +2. **Empowers polecats** - Can file discovered work that's out of their purview +3. **Beads handles work-disavowal** - Workers can close issues they didn't start +4. **Faster feedback** - No round-trip through Witness for issue creation + +## Complications + +For OSS projects where you're not a maintainer: +- Can't commit to the project's `.beads/` directory +- Need to file beads in a separate repo +- Beads supports this via `--root` flag + +## Subtask Designs + +--- + +### gt-zx3: Per-Rig Beads Configuration + +#### Config Location + +Per-rig configuration lives in the rig's config: + +**Option A: In rig state.json** (simpler) +``` +/config.json (or state.json) +``` + +**Option B: In town-level rigs.json** (centralized) +``` +config/rigs.json +``` + +Recommend **Option A** - each rig owns its config, easier to manage. + +#### Config Schema + +```json +// /config.json +{ + "version": 1, + "name": "wyvern", + "git_url": "https://github.com/steveyegge/wyvern", + + "beads": { + // Where polecats file beads + // Options: "local" | "" | "" + "repo": "local", + + // Override bd --root (optional, derived from repo if not set) + "root": null, + + // Issue prefix for this rig (used by bd create) + "prefix": "wyv" + } +} +``` + +#### Repo Options + +| Value | Meaning | Use Case | +|-------|---------|----------| +| `"local"` | Use project's `.beads/` | Own projects, full commit access | +| `""` | Use beads at path | OSS contributions, external beads | +| `""` | Clone and use repo | Team shared beads | + +#### Examples + +**Local project (default)**: +```json +{ + "beads": { + "repo": "local", + "prefix": "wyv" + } +} +``` + +**OSS contribution** (can't commit to project): +```json +{ + "beads": { + "repo": "/home/user/my-beads/react-contributions", + "prefix": "react" + } +} +``` + +**Team shared beads**: +```json +{ + "beads": { + "repo": "https://github.com/myteam/shared-beads", + "prefix": "team" + } +} +``` + +#### Environment Variable Injection + +When spawning polecats, Gas Town sets: + +```bash +export BEADS_ROOT="" +# Polecats use bd normally; it respects BEADS_ROOT +``` + +Or pass explicit flag in spawn: +```bash +# Gas Town wraps bd calls internally +bd --root "$BEADS_ROOT" create --title="..." +``` + +#### Resolution Logic + +```go +func ResolveBeadsRoot(rigConfig *RigConfig, rigPath string) (string, error) { + beads := rigConfig.Beads + + switch { + case beads.Root != "": + // Explicit root override + return beads.Root, nil + + case beads.Repo == "local" || beads.Repo == "": + // Use project's .beads/ + return filepath.Join(rigPath, ".beads"), nil + + case strings.HasPrefix(beads.Repo, "/") || strings.HasPrefix(beads.Repo, "~"): + // Absolute path + return expandPath(beads.Repo), nil + + case strings.Contains(beads.Repo, "://"): + // Git URL - need to clone + return cloneAndResolve(beads.Repo) + + default: + // Relative path from rig + return filepath.Join(rigPath, beads.Repo), nil + } +} +``` + +--- + +### gt-e1y: Worker Prompting - Beads Write Access + +Add to polecat CLAUDE.md template (AGENTS.md.template): + +```markdown +## Beads Access + +You have **full beads access** - you can create, update, and close issues. + +### Quick Reference + +```bash +# View available work +bd ready # Issues ready to work (no blockers) +bd list # All open issues +bd show # Issue details + +# Create issues +bd create --title="Fix login bug" --type=bug --priority=2 +bd create --title="Add dark mode" --type=feature + +# Update issues +bd update --status=in_progress # Claim work +bd close # Mark complete +bd close --reason="Duplicate of " + +# Sync (required before merge!) +bd sync # Commit beads changes to git +bd sync --status # Check if sync needed +``` + +### When to Create Issues + +Create beads issues when you discover work that: +- Is outside your current task scope +- Would benefit from tracking +- Should be done by someone else (or future you) + +**Good examples**: +```bash +# Found a bug while implementing feature +bd create --title="Race condition in auth middleware" --type=bug --priority=1 + +# Noticed missing documentation +bd create --title="Document API rate limits" --type=task --priority=3 + +# Tech debt worth tracking +bd create --title="Refactor legacy payment module" --type=task --priority=4 +``` + +**Don't create issues for**: +- Tiny fixes you can do in 2 minutes (just do them) +- Vague "improvements" with no clear scope +- Work that's already tracked elsewhere + +### Issue Lifecycle + +``` +┌─────────┐ ┌─────────────┐ ┌──────────┐ +│ open │───►│ in_progress │───►│ closed │ +└─────────┘ └─────────────┘ └──────────┘ + │ ▲ + └───────────────────────────────────┘ + (can close directly) +``` + +You can close issues without claiming them first. +Useful for quick fixes or discovered duplicates. + +### Beads Sync Protocol + +**CRITICAL**: Always sync beads before merging to main! + +```bash +# Before your final merge +bd sync # Commits beads changes +git status # Should show .beads/ changes +git add .beads/ +git commit -m "beads: sync" +# Then proceed with merge to main +``` + +If you forget to sync, your beads changes will be lost when your session ends. + +### Your Beads Repo + +Your beads are configured for this rig. You don't need to specify --root. +Just use `bd` commands normally. + +To check where your beads go: +```bash +bd config show root +``` +``` + +--- + +### gt-cjb: Witness Updates - Remove Issue Filing Proxy + +Update Witness CLAUDE.md to remove proxy responsibilities: + +**REMOVE from Witness prompting**: + +```markdown +## Issue Filing Proxy (REMOVED) + +The following is NO LONGER your responsibility: +- Processing polecat "file issue" mail requests +- Creating issues on behalf of polecats +- Forwarding issue creation requests + +Polecats now have direct beads write access and file their own issues. +``` + +**KEEP in Witness prompting** (from swarm-shutdown-design.md): +- Monitoring polecat progress +- Nudge protocol +- Pre-kill verification +- Session lifecycle management + +**UPDATE**: If Witness receives an old-style "please file issue" request: + +```markdown +### Legacy Issue Filing Requests + +If you receive a mail asking you to file an issue on a polecat's behalf: + +1. **Respond with update**: +```bash +town inject "UPDATE: You have direct beads access now. Use 'bd create --title=\"...\" --type=...' to file issues yourself." +``` + +2. **Don't file the issue yourself** - let the polecat learn the new workflow. +``` + +--- + +### gt-082: Worker Cleanup - Beads Sync on Shutdown + +This integrates with swarm-shutdown-design.md decommission checklist. + +**Update to decommission checklist** (addition to gt-sd6): + +```markdown +## Decommission Checklist (Updated) + +### Pre-Done Verification + +```bash +# 1. Git status - must be clean +git status +# Expected: "nothing to commit, working tree clean" + +# 2. Stash list - must be empty +git stash list +# Expected: (empty) + +# 3. Beads sync - MUST be synced +bd sync --status +# Expected: "Up to date" or "Nothing to sync" +# If not: run 'bd sync' first! + +# 4. Beads committed - verify in git +git status +# Expected: .beads/ should NOT show changes +# If it does: git add .beads/ && git commit -m "beads: sync" + +# 5. Branch merged to main +git log main --oneline -1 +git log HEAD --oneline -1 +# Expected: Same commit +``` + +### Beads Edge Cases + +**Uncommitted beads changes**: +```bash +bd sync # Commits to .beads/ +git add .beads/ +git commit -m "beads: final sync" +``` + +**Beads sync conflict** (rare): +```bash +# If bd sync fails with conflict: +git fetch origin main +git checkout main -- .beads/ +bd sync --force # Re-apply your changes +git add .beads/ +git commit -m "beads: resolve sync conflict" +``` +``` + +**Update to Witness pre-kill verification** (addition to gt-f8v): + +```markdown +### Beads-Specific Verification + +When capturing worker state, also check beads: + +```bash +town capture "bd sync --status && git status .beads/" +``` + +**Check for**: +- `bd sync --status` shows "Up to date" +- `git status .beads/` shows no changes + +**If beads not synced**: +``` +town inject "WITNESS CHECK: Beads not synced. Run 'bd sync' then 'git add .beads/ && git commit -m \"beads: sync\"'. Signal done again when complete." +``` +``` + +--- + +## Config File Examples + +### Rig with local beads (default) + +```json +// gastown/config.json +{ + "version": 1, + "name": "gastown", + "git_url": "https://github.com/steveyegge/gastown", + "beads": { + "repo": "local", + "prefix": "gt" + } +} +``` + +### Rig contributing to OSS project + +```json +// react/config.json +{ + "version": 1, + "name": "react", + "git_url": "https://github.com/facebook/react", + "beads": { + "repo": "/home/steve/my-beads/react", + "prefix": "react" + } +} +``` + +### Rig with team shared beads + +```json +// internal-app/config.json +{ + "version": 1, + "name": "internal-app", + "git_url": "https://github.com/mycompany/internal-app", + "beads": { + "repo": "https://github.com/mycompany/team-beads", + "prefix": "app" + } +} +``` + +--- + +## Migration Notes + +### For Existing Rigs + +1. Add `beads` section to rig config.json +2. Default to `"repo": "local"` if not specified +3. Update polecat CLAUDE.md templates +4. Remove Witness proxy code + +### Backwards Compatibility + +- If `beads` section missing, assume `"repo": "local"` +- Old-style "file issue" mail requests get redirect nudge +- No breaking changes for polecats already using bd read commands + +--- + +## Implementation Checklist + +- [ ] Add beads config schema to rig config (gt-zx3) +- [ ] Update polecat CLAUDE.md template with bd write access (gt-e1y) +- [ ] Update Witness CLAUDE.md to remove proxy, add redirect (gt-cjb) +- [ ] Update decommission checklist with beads sync (gt-082) +- [ ] Update Witness verification to check beads sync (gt-082) +- [ ] Add BEADS_ROOT environment injection to spawn logic diff --git a/docs/swarm-shutdown-design.md b/docs/swarm-shutdown-design.md new file mode 100644 index 00000000..3c214702 --- /dev/null +++ b/docs/swarm-shutdown-design.md @@ -0,0 +1,554 @@ +# Swarm Shutdown Design + +Design for graceful swarm shutdown, worker cleanup, and session cycling. + +**Epic**: gt-82y (Design: Swarm shutdown and worker cleanup) + +## Key Decisions (from ultrathink) + +1. **Pre-kill verification uses model intelligence** - Witness assesses git status output, not framework rules +2. **Witness can request restart** - Mail self handoff notes, exit cleanly when context filling +3. **Mayor NOT involved in per-worker cleanup** - That's Witness's domain +4. **Polecats verify themselves first** - Decommission checklist in prompting, Witness double-checks + +## Responsibility Boundaries (gt-gl2) + +### Mayor Responsibilities +- Swarm dispatch and strategic planning +- Cross-rig coordination +- Escalation handling (when Witness reports blocked workers) +- Final integration decisions +- **NOT**: Per-worker cleanup, session killing, nudging + +### Witness Responsibilities +- Monitor worker health and progress +- Nudge workers toward completion +- Pre-kill verification (capture & assess git status) +- Session lifecycle (kill, restart workers) +- Self session cycling (mail handoff, exit) +- Report blocked workers to Mayor for escalation +- **NOT**: Implementation work, cross-rig coordination + +### Polecat Responsibilities +- Complete assigned work +- Self-verify before signaling done (decommission checklist) +- Respond to Witness nudges +- **NOT**: Killing own session, coordinating with other polecats directly + +## Subtask Designs + +--- + +### gt-sd6: Enhanced Polecat Decommission Prompting + +Add to polecat CLAUDE.md template (AGENTS.md.template): + +```markdown +## Decommission Checklist + +**CRITICAL**: Before signaling you are done, you MUST complete this checklist. +The Witness will verify each item and bounce you back if anything is dirty. + +### Pre-Done Verification + +Run these commands and verify ALL are clean: + +```bash +# 1. Git status - must be clean (no uncommitted changes) +git status +# Expected: "nothing to commit, working tree clean" + +# 2. Stash list - must be empty (no forgotten stashes) +git stash list +# Expected: (empty output) + +# 3. Beads sync - must be up to date +bd sync --status +# Expected: "Up to date" or "Nothing to sync" + +# 4. Branch merged - your work must be on main +git log main --oneline -1 +git log HEAD --oneline -1 +# Expected: Same commit (your branch is merged) +``` + +### If Any Check Fails + +- **Uncommitted changes**: Commit them or discard if truly unnecessary +- **Stashes**: Pop and commit, or drop if obsolete +- **Beads out of sync**: Run `bd sync` +- **Branch not merged**: Complete the merge workflow + +### Signaling Done + +Only after ALL checks pass: + +```bash +# Close your issue +bd close + +# Final sync +bd sync + +# Signal ready for decommission +town mail send /witness -s "Work Complete" -m "Issue done. Checklist verified." +``` + +The Witness will capture your git state and verify before killing your session. +If anything is dirty, you'll receive a nudge with specific issues to fix. +``` + +--- + +### gt-f8v: Witness Pre-Kill Verification Protocol + +Add to Witness CLAUDE.md template: + +```markdown +## Pre-Kill Verification Protocol + +Before killing any worker session, you MUST verify their workspace is clean. +Use your judgment on the output - don't rely on pattern matching. + +### Verification Steps + +When a worker signals done: + +1. **Capture worker state**: +```bash +# Attach and capture git status +town capture "git status && git stash list && git log --oneline -3" +``` + +2. **Assess the output** (use your judgment): +- Is working tree clean? (no modified/untracked files that matter) +- Is stash list empty? (or only contains intentional stashes) +- Does recent history show their work is committed? + +3. **Decision**: +- **CLEAN**: Proceed to kill session +- **DIRTY**: Send nudge with specific issues + +### Nudge Templates + +**Uncommitted Changes**: +``` +town inject "WITNESS CHECK: You have uncommitted changes. Please commit or discard: . Signal done again when clean." +``` + +**Stash Not Empty**: +``` +town inject "WITNESS CHECK: You have stashed changes. Please pop and commit, or drop if obsolete: . Signal done again when clean." +``` + +**Work Not Merged**: +``` +town inject "WITNESS CHECK: Your commits are not on main. Please complete merge workflow. Signal done again when merged." +``` + +**Multiple Issues**: +``` +town inject "WITNESS CHECK: Multiple issues found: +1. +2. +Please resolve all and signal done again." +``` + +### Kill Sequence + +Only after verification passes: + +```bash +# Log the verification +echo "[$(date)] Verified clean: " >> witness/verification.log + +# Kill the session +town kill + +# Update state +town sleep +``` + +### Escalation + +If a worker fails verification 3+ times or becomes unresponsive: + +```bash +town mail send mayor/ -s "Escalation: stuck" -m "Worker cannot complete cleanup after 3 attempts. Issues: . Requesting guidance." +``` +``` + +--- + +### gt-eu9: Witness Session Cycling and Handoff + +Add to Witness CLAUDE.md template: + +```markdown +## Session Cycling + +Your context will fill over long swarms. When you notice significant context usage +or feel you're losing track of state, proactively cycle your session. + +### Recognizing When to Cycle + +Signs you should cycle: +- You've been running for many hours +- You're losing track of which workers you've checked +- Responses are getting slower or less coherent +- You're about to start a complex operation + +### Handoff Protocol + +1. **Capture current state**: +```bash +# Check all worker states +town list . + +# Check pending verifications +town all beads + +# Check your inbox for unprocessed messages +town inbox +``` + +2. **Compose handoff note**: +```bash +town mail send /witness -s "Session Handoff" -m "$(cat <<'EOF' +[HANDOFF_TYPE]: witness_cycle +[TIMESTAMP]: $(date -Iseconds) +[RIG]: + +## Active Workers + + +## Pending Verifications + + +## Recent Actions + + +## Warnings/Notes + + +## Next Steps + +EOF +)" +``` + +3. **Exit cleanly**: +```bash +# Ensure no pending operations +# Then simply end your session - the daemon will spawn a fresh one +``` + +### Handoff Note Format + +The handoff note uses metadata format for parseability: + +``` +[HANDOFF_TYPE]: witness_cycle +[TIMESTAMP]: 2024-01-15T10:30:00Z +[RIG]: gastown + +## Active Workers +- Furiosa: working on gt-abc1 (spawned 2h ago) +- Toast: idle, awaiting assignment +- Capable: signaled done, pending verification + +## Pending Verifications +- Capable: signaled done at 10:25, not yet verified + +## Recent Actions +1. Verified and killed Nux (gt-xyz9 complete) +2. Spawned Furiosa on gt-abc1 +3. Received done signal from Capable + +## Warnings/Notes +- Furiosa has been quiet for 30min, may need nudge +- Integration branch has 3 merged PRs + +## Next Steps +1. Verify Capable's workspace +2. Check on Furiosa's progress +3. Report status to Refinery if all workers done +``` + +### On Fresh Session Start + +When you start (or restart after cycling): + +1. **Check for handoff**: +```bash +town inbox | grep "Session Handoff" +``` + +2. **If handoff exists, read it**: +```bash +town read +``` + +3. **Resume from handoff state** - pick up pending verifications, check noted workers + +4. **If no handoff** - do full status check: +```bash +town list . +town all beads +``` +``` + +--- + +### gt-gl2: Mayor vs Witness Cleanup Documentation + +This goes in the main Gas Town documentation or CLAUDE.md templates. + +```markdown +## Cleanup Authority Model + +Gas Town uses a clear separation of cleanup responsibilities: + +### The Rule +**Witness handles ALL per-worker cleanup. Mayor is never involved.** + +### Why This Matters + +1. **Separation of concerns**: Mayor thinks strategically, Witness thinks operationally +2. **Reduced coordination overhead**: No back-and-forth for routine cleanup +3. **Faster shutdown**: Witness can kill workers immediately upon verification +4. **Cleaner escalation**: Mayor only hears about problems, not routine operations + +### What "Cleanup" Means + +Witness handles: +- Verifying worker git state before kill +- Nudging workers to fix dirty state +- Killing worker sessions +- Updating worker state (sleep/wake) +- Logging verification results + +Mayor handles: +- Receiving "swarm complete" notifications +- Deciding whether to start new swarms +- Handling escalations (stuck workers after multiple retries) +- Cross-rig coordination if workers need to hand off + +### Escalation Path + +``` +Worker stuck -> Witness nudges (up to 3x) -> Witness escalates to Mayor + -> Mayor decides: force kill, reassign, or human intervention +``` + +### Anti-Patterns + +**DON'T**: Have Mayor ask Witness "is worker X clean?" +**DO**: Have Witness report "swarm complete, all workers verified and killed" + +**DON'T**: Have Mayor kill worker sessions directly +**DO**: Have Mayor tell Witness "abort swarm" and let Witness handle cleanup + +**DON'T**: Have workers report done to Mayor +**DO**: Have workers report done to Witness, Witness aggregates and reports to Refinery/Mayor +``` + +--- + +## Mail Templates (additions to templates.py) + +### WORKER_DONE (Worker -> Witness) + +```python +def worker_done( + sender: str, + rig: str, + issue_id: str, + checklist_verified: bool = True, +) -> Message: + """Worker signals completion to Witness.""" + metadata = { + "template": "WORKER_DONE", + "rig": rig, + "issue": issue_id, + "checklist_verified": checklist_verified, + } + + body = f"""Work complete on {issue_id}. + +{_format_metadata(metadata)} + +Decommission checklist {'verified' if checklist_verified else 'NOT verified - please check'}. +Ready for verification and session termination. +""" + return Message.create( + sender=sender, + recipient=f"{rig}/witness", + subject=f"Work Complete: {issue_id}", + body=body, + ) +``` + +### VERIFICATION_FAILED (Witness -> Worker, via inject) + +```python +def verification_failed( + worker: str, + issues: List[str], +) -> str: + """Generate nudge text for failed verification (injected, not mailed).""" + issues_text = "\n".join(f" - {issue}" for issue in issues) + return f"""WITNESS VERIFICATION FAILED + +The following issues must be resolved before decommission: +{issues_text} + +Please fix these issues and signal done again. +""" +``` + +### WITNESS_HANDOFF (Witness -> Witness) + +```python +def witness_handoff( + sender: str, + rig: str, + active_workers: List[Dict], + pending_verifications: List[str], + recent_actions: List[str], + warnings: Optional[str] = None, + next_steps: List[str] = None, +) -> Message: + """Witness session handoff note.""" + metadata = { + "template": "WITNESS_HANDOFF", + "rig": rig, + "timestamp": datetime.utcnow().isoformat(), + "active_worker_count": len(active_workers), + "pending_verification_count": len(pending_verifications), + } + + # Format workers + workers_text = "\n".join( + f"- {w['name']}: {w['status']}" for w in active_workers + ) or "None" + + # Format pending + pending_text = "\n".join(f"- {p}" for p in pending_verifications) or "None" + + # Format actions + actions_text = "\n".join(f"{i+1}. {a}" for i, a in enumerate(recent_actions[-5:])) + + body = f"""Session handoff for {rig} Witness. + +{_format_metadata(metadata)} + +## Active Workers +{workers_text} + +## Pending Verifications +{pending_text} + +## Recent Actions +{actions_text} + +## Warnings +{warnings or "None"} + +## Next Steps +{chr(10).join(f"- {s}" for s in (next_steps or ["Check pending verifications"]))} +""" + return Message.create( + sender=sender, + recipient=f"{rig}/witness", + subject="Session Handoff", + body=body, + ) +``` + +### ESCALATION (Witness -> Mayor) + +```python +def worker_escalation( + sender: str, + rig: str, + worker: str, + issue_id: str, + attempts: int, + unresolved_issues: List[str], +) -> Message: + """Witness escalates stuck worker to Mayor.""" + metadata = { + "template": "WORKER_ESCALATION", + "rig": rig, + "worker": worker, + "issue": issue_id, + "verification_attempts": attempts, + } + + issues_text = "\n".join(f" - {i}" for i in unresolved_issues) + + body = f"""Worker {worker} cannot complete cleanup. + +{_format_metadata(metadata)} + +After {attempts} verification attempts, the following issues remain: +{issues_text} + +Requesting guidance: +1. Force kill and abandon changes? +2. Reassign to another worker? +3. Escalate to human? +""" + return Message.create( + sender=sender, + recipient="mayor/", + subject=f"Escalation: {worker} stuck on {issue_id}", + body=body, + priority="high", + ) +``` + +--- + +## Implementation Notes + +### Verification State Tracking + +Witness should track verification attempts in memory (or state.json): + +```json +{ + "pending_verifications": { + "Furiosa": { + "issue_id": "gt-abc1", + "signaled_at": "2024-01-15T10:25:00Z", + "attempts": 1, + "last_issues": ["uncommitted changes in src/foo.py"] + } + } +} +``` + +### Nudge vs Mail + +- **Nudge (inject)**: For immediate attention - verification failures, progress checks +- **Mail**: For async communication - handoffs, escalations, status reports + +### Timeout Handling + +If worker doesn't respond to nudge within reasonable time: +1. First: Re-nudge with more urgency +2. Second: Capture their session state for diagnostics +3. Third: Escalate to Mayor + +--- + +## Checklist for Implementation + +- [ ] Update AGENTS.md.template with decommission checklist (gt-sd6) +- [ ] Create WITNESS_CLAUDE.md template with verification protocol (gt-f8v) +- [ ] Add session cycling to Witness prompting (gt-eu9) +- [ ] Document cleanup authority in main docs (gt-gl2) +- [ ] Add mail templates to templates.py +- [ ] Add verification state to Witness state.json schema