docs: add design docs for swarm shutdown, polecat beads, and mayor handoff
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||||
|
<per-rig swarm status>
|
||||||
|
|
||||||
|
## Rig Status
|
||||||
|
<health/state of each rig>
|
||||||
|
|
||||||
|
## Pending Escalations
|
||||||
|
<issues awaiting Mayor decision>
|
||||||
|
|
||||||
|
## In-Flight Decisions
|
||||||
|
<decisions being made, context needed>
|
||||||
|
|
||||||
|
## Recent Actions
|
||||||
|
<last 5-10 significant actions>
|
||||||
|
|
||||||
|
## Delegated Work
|
||||||
|
<work sent to refineries, awaiting response>
|
||||||
|
|
||||||
|
## User Requests
|
||||||
|
<any pending user requests>
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
<what the next session should do>
|
||||||
|
|
||||||
|
## Warnings/Notes
|
||||||
|
<anything critical for next session>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 "<handoff-content>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 <latest-handoff-id>
|
||||||
|
|
||||||
|
# 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]: <current time>
|
||||||
|
[SESSION_DURATION]: <how long you've been running>
|
||||||
|
|
||||||
|
## Active Swarms
|
||||||
|
<list each rig with active swarm, workers, progress>
|
||||||
|
|
||||||
|
## Rig Status
|
||||||
|
<table of rig health>
|
||||||
|
|
||||||
|
## Pending Escalations
|
||||||
|
<issues needing your decision>
|
||||||
|
|
||||||
|
## In-Flight Decisions
|
||||||
|
<decisions you were making>
|
||||||
|
|
||||||
|
## Recent Actions
|
||||||
|
<last 5-10 things you did>
|
||||||
|
|
||||||
|
## Delegated Work
|
||||||
|
<work sent to refineries>
|
||||||
|
|
||||||
|
## User Requests
|
||||||
|
<any pending user asks>
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
<what next session should do>
|
||||||
|
|
||||||
|
## Warnings/Notes
|
||||||
|
<critical info for next session>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Send handoff**:
|
||||||
|
```bash
|
||||||
|
town mail send mayor/ -s "Session Handoff" -m "<your handoff note>"
|
||||||
|
```
|
||||||
|
|
||||||
|
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 <msg-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
@@ -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)
|
||||||
|
```
|
||||||
|
<rig>/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
|
||||||
|
// <rig>/config.json
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"name": "wyvern",
|
||||||
|
"git_url": "https://github.com/steveyegge/wyvern",
|
||||||
|
|
||||||
|
"beads": {
|
||||||
|
// Where polecats file beads
|
||||||
|
// Options: "local" | "<path>" | "<git-url>"
|
||||||
|
"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 |
|
||||||
|
| `"<path>"` | Use beads at path | OSS contributions, external beads |
|
||||||
|
| `"<git-url>"` | 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="<resolved-path>"
|
||||||
|
# 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 <id> # 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 <id> --status=in_progress # Claim work
|
||||||
|
bd close <id> # Mark complete
|
||||||
|
bd close <id> --reason="Duplicate of <other>"
|
||||||
|
|
||||||
|
# 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 <polecat> "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 <polecat> "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 <polecat> "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
|
||||||
@@ -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 <issue-id>
|
||||||
|
|
||||||
|
# Final sync
|
||||||
|
bd sync
|
||||||
|
|
||||||
|
# Signal ready for decommission
|
||||||
|
town mail send <rig>/witness -s "Work Complete" -m "Issue <id> 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 <polecat> "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 <polecat> "WITNESS CHECK: You have uncommitted changes. Please commit or discard: <list files>. Signal done again when clean."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Stash Not Empty**:
|
||||||
|
```
|
||||||
|
town inject <polecat> "WITNESS CHECK: You have stashed changes. Please pop and commit, or drop if obsolete: <stash list>. Signal done again when clean."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Work Not Merged**:
|
||||||
|
```
|
||||||
|
town inject <polecat> "WITNESS CHECK: Your commits are not on main. Please complete merge workflow. Signal done again when merged."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Multiple Issues**:
|
||||||
|
```
|
||||||
|
town inject <polecat> "WITNESS CHECK: Multiple issues found:
|
||||||
|
1. <issue 1>
|
||||||
|
2. <issue 2>
|
||||||
|
Please resolve all and signal done again."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kill Sequence
|
||||||
|
|
||||||
|
Only after verification passes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Log the verification
|
||||||
|
echo "[$(date)] Verified clean: <polecat>" >> witness/verification.log
|
||||||
|
|
||||||
|
# Kill the session
|
||||||
|
town kill <polecat>
|
||||||
|
|
||||||
|
# Update state
|
||||||
|
town sleep <polecat>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Escalation
|
||||||
|
|
||||||
|
If a worker fails verification 3+ times or becomes unresponsive:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
town mail send mayor/ -s "Escalation: <polecat> stuck" -m "Worker <polecat> cannot complete cleanup after 3 attempts. Issues: <list>. 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 <rig>/witness -s "Session Handoff" -m "$(cat <<'EOF'
|
||||||
|
[HANDOFF_TYPE]: witness_cycle
|
||||||
|
[TIMESTAMP]: $(date -Iseconds)
|
||||||
|
[RIG]: <rig>
|
||||||
|
|
||||||
|
## Active Workers
|
||||||
|
<list workers and their current status>
|
||||||
|
|
||||||
|
## Pending Verifications
|
||||||
|
<workers who signaled done but not yet verified>
|
||||||
|
|
||||||
|
## Recent Actions
|
||||||
|
<last 3-5 actions taken>
|
||||||
|
|
||||||
|
## Warnings/Notes
|
||||||
|
<anything the next session should know>
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
<what should happen next>
|
||||||
|
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 <handoff-msg-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user