Molecule CLI: bd molecule commands

Add molecule commands to bd:

## Commands

```bash
bd molecule list              # List molecules (type: molecule)
bd molecule show <id>         # Show molecule with parsed steps
bd molecule parse <id>        # Validate and show parsed structure
bd molecule instantiate <mol-id> --parent=<issue-id>  # Create steps
bd molecule instances <mol-id>  # Show all instantiations
```

## gt spawn integration

```bash
gt spawn --issue <id> --molecule <mol-id>
```

This should:
1. Call `bd molecule instantiate` (creates child beads atomically)
2. Spawn polecat on first ready step
3. Polecat grinds through via `bd ready`

## Output Examples

```
$ bd molecule show mol-abc

mol-abc: Engineer in a Box
Type: molecule

Steps (5):
  design      → (ready first)
  implement   → Needs: design
  review      → Needs: implement
  test        → Needs: implement
  submit      → Needs: review, test

Instances: 3
```

```
$ bd molecule instances mol-abc

Parent          Status    Created
gt-xyz          done      2025-12-15
gt-abc          active    2025-12-17 (3/5 complete)
gt-def          pending   2025-12-18
```


Digest: mol-deacon-patrol @ 2025-12-24 19:26

Patrol 11: 8 sessions OK


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously,
handling callbacks, monitoring rig health, and performing cleanup.
Each patrol cycle runs these steps in sequence, then loops or exits.


mol-deacon-patrol


Witness should verify polecat submitted before stopping session

## Problem

Witness stopped dementus's session before it could call `gt done`, losing the MR submission. I had to manually push and submit the branch.

## Root Cause

Witness cleanup is triggered by nudge/manual check rather than by receiving POLECAT_DONE message. When Witness cleans up based on issue status (closed), it doesn't wait for the polecat to complete its shutdown sequence.

## Expected Behavior

Witness should only stop a polecat session after:
1. Receiving POLECAT_DONE message from that polecat, OR
2. Timeout waiting for POLECAT_DONE after issue is closed

## Current Behavior

Witness stops sessions immediately when asked to check for completions, even if polecat hasn't called `gt done` yet.

## Fix

In mol-witness-patrol inbox-check step:
- Only clean up polecats that have sent POLECAT_DONE
- For polecats with closed issues but no DONE message, nudge them to complete
- Add timeout before force-killing


Track operational stats as entity/audit beads

Witness and refinery track operational stats in JSON files:
- total_merged, today_merged, total_failed (refinery)
- total_checks, total_nudges, total_escalations (witness)

For HOP entity CV tracking, these could become:
- type=audit beads (daily roll-ups of operational metrics)
- Entity chain entries showing validator activity

This provides observability and contributes to entity reputation tracking (e.g., refinery X has merged 500 PRs with 2% failure rate).

Not critical for launch but aligns with HOP Platform of Platforms vision.


Merge: gt-rana.4

branch: polecat/ace
target: main
source_issue: gt-rana.4
rig: gastown


Digest: mol-deacon-patrol

Patrol 8: All healthy


Crew workers getting wrong CLAUDE.md (shows Refinery)

## Problem

Crew workers (emma, dave) have CLAUDE.md that says they're the Refinery.

## Evidence

```
$ head -5 /Users/stevey/gt/beads/crew/emma/CLAUDE.md
# Claude: Beads Refinery
You are the **Refinery** for the **beads** rig...
```

## Expected

Should use crew.md.tmpl which correctly says:
```
# Crew Worker Context
You are a **crew worker** - the overseer's (human's) personal workspace...
```

## Impact

- Crew workers have wrong identity in static context
- `gt prime` correctly outputs crew context, but CLAUDE.md conflicts
- Confusing role information

## Fix

Check `gt crew create` or whatever populates CLAUDE.md for crew workers.


gt crew refresh: Context cycling with handoff

Implement 'gt crew refresh <name>' command:
- Send handoff mail to self (context summary)
- Kill current session cleanly
- Start new session
- New session reads handoff mail and resumes
- Support --message to add custom handoff notes


Remove bd sync instruction from polecat startup workflow

Polecats are instructed to run `bd sync --from-main` on startup (spawn.go:634).

## Problem
- Spawn command already syncs beads before spawning (line 239)
- Polecats share rig-level beads via `.beads/redirect`
- Multiple polecats starting simultaneously all try to sync same shared beads
- This causes git conflicts/failures when many polecats spawn at once

## Observed
User reported: 'all polecats failing on beads sync on startup in one run'

## Fix
Remove line 634 from buildWorkAssignmentMail():
```
body.WriteString("2. Run \`bd sync --from-main\` to get fresh beads\n")
```

Polecats only need to sync at END of work (already in steps 5/7).

## Files
- internal/cmd/spawn.go: buildWorkAssignmentMail() and buildSpawnContext()


Digest: mol-deacon-patrol

Patrol 20: Routine - handoff threshold reached


Digest: mol-deacon-patrol

Patrol 2: inbox clear, all agents healthy


Rename Engineer in Box to Shiny

Rename mol-engineer-in-box to mol-shiny (or just 'shiny').

Mad Max reference - the canonical 'right way to engineer'.
Update all references in docs and code.


Digest: mol-deacon-patrol

Patrol 19


Test Polecat Arm

Test child for bonding pattern


Tech Debt: Code Review December 2024

Tech debt identified during code review on 2024-12-21. Contains 11 issues ranging from P2-P4 covering:

- Code duplication (manager creation boilerplate)
- Test coverage gaps (cmd 6.8%, mail 3.6%)
- Magic strings needing constants
- Error handling inconsistencies
- Large files needing splitting
- Unused code removal

Work through these incrementally to improve codebase maintainability.


Digest: mol-deacon-patrol

Patrol #15: Stable


Digest: mol-deacon-patrol

Patrol 1: All agents healthy, no messages, no issues


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.


mol-deacon-patrol


MQ config schema: merge_queue section in rig config.json

Define and implement merge_queue configuration in rig config.

Schema:
{
  "merge_queue": {
    "enabled": true,
    "target_branch": "main",
    "integration_branches": true,
    "on_conflict": "assign_back",  // or "auto_rebase"
    "run_tests": true,
    "test_command": "go test ./...",
    "delete_merged_branches": true,
    "retry_flaky_tests": 1,
    "poll_interval": "30s",
    "max_concurrent": 1
  }
}

Implement:
- Config loading in rig package
- Default values
- Validation

Reference: docs/merge-queue-design.md#configuration


gt polecat add: should handle existing branch gracefully

## Problem

`gt polecat add gastown Nux` fails if the branch `polecat/Nux` already exists.

## Current Behavior

```
fatal: a branch named 'polecat/Nux' already exists
```

## Expected Behavior

Should either:
1. Reuse the existing branch
2. Or prompt to delete/recreate
3. Or auto-suffix: polecat/Nux-2

## Context

Branch may exist from previous polecat that was removed but branch wasn't cleaned up.


Implement meta-formula generator in parser

Implement the generator that expands meta-formulas into concrete formulas.

## Implementation

1. Detect type: meta-formula in parser
2. Evaluate for-each values
3. For each value, instantiate the formula template
4. Substitute {var} placeholders with current value
5. Return list of generated Formula structs

## API

    func (p *Parser) ExpandMetaFormula(mf *MetaFormula) ([]*Formula, error)

## Edge Cases

- Empty values list: return empty slice
- Duplicate generated names: error
- Nested meta-formulas: error (not supported initially)


Test Patrol Parent

Test parent for Christmas Ornament pattern


mol-swarm-cleanup: Post-swarm debris cleanup molecule

After a 20+ worker swarm completed, found significant beads debris:
- 18 stale messages (work assignments, lifecycle requests, swarm instructions)
- 3 completed issues still open/in_progress
- Test messages accumulated

Need: Document a post-swarm checklist or create gt swarm cleanup command that:
1. Closes stale work assignment messages
2. Reviews in_progress issues for completion
3. Closes orphaned lifecycle messages
4. Optionally archives test messages


Document harness concept in docs/harness.md

Create comprehensive harness documentation:
- What is a harness (installation directory)
- Recommended structure and naming
- .beads/redirect for default project
- config/ contents (rigs.json, town.json)
- Mayor home vs rig-level mayor/
- Example configurations
- Relationship to rigs


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously,
handling callbacks, monitoring rig health, and performing cleanup.
Each patrol cycle runs these steps in sequence, then loops or exits.


Phase 1.3: mol-deacon-patrol definition

Define the Deacon patrol molecule in builtin_molecules.go.

## Steps
1. inbox-check - Handle callbacks from agents
2. health-scan - Ping Witnesses and Refineries
3. plugin-run - Execute registered plugins
4. orphan-check - Find abandoned work
5. session-gc - Clean dead sessions
6. context-check - Check own context limit
7. loop-or-exit - Burn and let daemon respawn, or exit if context high

## Implementation
- Add DeaconPatrolMolecule() to builtin_molecules.go
- Add to BuiltinMolecules() list
- Test with bd mol show mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 9: All healthy


Digest: mol-deacon-patrol @ 2025-12-24 19:28

Patrol 17


Digest: mol-deacon-patrol

Patrol 7: All healthy


Digest: mol-deacon-patrol

Patrol 3: all healthy


Self-review

Review your own changes. Look for:
- Bugs and edge cases
- Style issues
- Missing error handling
- Security concerns

Fix any issues found before proceeding.


Work on gt-role-template: Refine witness/CLAUDE.md role t...

Work on gt-role-template: Refine witness/CLAUDE.md role template. See issue for details. Run 'bd show gt-role-template' to see the full issue.


Auto-handoff: self-cycling with guaranteed work pickup

## Summary

A mechanism for agents to self-cycle: send handoff mail, request Deacon to kill the process, and automatically restart to pick up the work.

## Use Case

User says: `auto-handoff: gt-bug3`

The agent:
1. Sends handoff mail documenting current state
2. Requests Deacon to terminate the session
3. Deacon restarts the agent in background
4. New session picks up the handoff and continues working

When the user returns to terminal, the old session is gone but work continues in background. User can reattach.

## Key Requirements

- **Guaranteed pickup**: Something in the hook and/or handoff must ensure the new session picks up the work (not just a passive "check inbox")
- **Background execution**: Work continues without user presence
- **Reattachability**: User can reconnect to see progress

## Design Questions

1. Can molecules help coordinate this? (e.g., molecule binds the handoff + auto-restart)
2. What hook handles the pickup guarantee?
3. How does Deacon know to restart vs just kill?
4. How does user reattach to a background agent?

## Related

- Molecules system
- Deacon lifecycle management
- Handoff hooks


Witness swarm landing protocol

Witness responsibilities for swarm landing cleanup.

## Trigger

Witness receives "swarm-landed" mail from Refinery containing:
- swarm_id
- merge_commit
- action: "cleanup"

## Landing Protocol

### Phase 1: Preflight
Verify all polecat sessions stopped:
- Check tmux for active sessions
- Kill any remaining sessions
- Wait for graceful shutdown

### Phase 2: Git Audit
For each polecat in swarm:
- Check for uncommitted changes
- Check for unpushed commits
- Check for stashes
- Classify as "beads-only" (safe) or "code at risk"
- If code at risk: escalate, abort landing

### Phase 3: Cleanup
For each polecat:
- Clear state entry (mark as idle)
- Delete inbox (or archive)
- Delete worker branch (local + remote)

### Phase 4: Final Report
- Update swarm state to "landed"
- File landing report bead
- Mail Mayor with summary

## Code at Risk Handling

If git audit finds code at risk:
1. Abort cleanup for that polecat
2. Mail Mayor with details
3. Human intervention required

## Reference

PGT: swarm/landing.py (6-phase protocol), swarm/git_audit.py


Digest: mol-deacon-patrol

Test patrol cycle - first run, no actual work done


Digest: mol-deacon-patrol

Patrol OK: archived old handoff, all agents up, furiosa on gt-oiv0


load-context

Run gt prime and bd prime. Verify issue assignment.
Check inbox for any relevant messages.

Read the assigned issue (gt-u2vg) and understand the requirements.
Identify any blockers or missing information.


Polecat template cleanup

Collection of improvements to the polecat role template (polecat.md.tmpl). Focus: reduce prose redundancy, move behavior into molecules, fix terminology, improve clarity.


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.


Digest: mol-deacon-patrol

Patrol 17: All healthy


mol-deacon-patrol


Cooking metadata: source tracing

Add source_formula and source_location metadata to cooked steps so you can trace a step in a proto back to its origin formula. Useful for debugging complex compositions.


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

This molecule is bonded dynamically by mol-witness-patrol's survey-workers step.
Each polecat being monitored gets one arm that runs in parallel with other arms.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| polecat_name | Yes | Name of the polecat to inspect |
| rig | Yes | Rig containing the polecat |

## Step: capture
Capture recent tmux output for toast.

```bash
tmux capture-pane -t gt-gastown-toast -p | tail -50
```

Record:
- Last activity timestamp (when was last tool call?)
- Visible errors or stack traces
- Completion indicators ("Done", "Finished", etc.)

## Step: assess
Categorize polecat state based on captured output.

States:
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **requesting_shutdown**: Sent LIFECYCLE/Shutdown mail
- **done**: Showing completion indicators

Calculate: minutes since last activity.
Needs: capture

## Step: load-history
Read nudge history for toast from patrol state.

```
nudge_count = state.nudges[toast].count
last_nudge_time = state.nudges[toast].timestamp
```

This data was loaded by the parent patrol's load-state step and passed
to the arm via the bonding context.
Needs: assess

## Step: decide
Apply the nudge matrix to determine action for toast.

| State | Idle Time | Nudge Count | Action |
|-------|-----------|-------------|--------|
| working | any | any | none |
| idle | <10min | any | none |
| idle | 10-15min | 0 | nudge-1 (gentle) |
| idle | 15-20min | 1 | nudge-2 (direct) |
| idle | 20+min | 2 | nudge-3 (final) |
| idle | any | 3 | escalate |
| error | any | any | assess-severity |
| requesting_shutdown | any | any | pre-kill-verify |
| done | any | any | pre-kill-verify |

Nudge text:
1. "How's progress? Need any help?"
2. "Please wrap up soon. What's blocking you?"
3. "Final check. Will escalate in 5 min if no response."

Record decision and rationale.
Needs: load-history

## Step: execute
Take the decided action for toast.

**nudge-N**:
```bash
tmux send-keys -t gt-gastown-toast "{{nudge_text}}" Enter
```

**pre-kill-verify**:
```bash
cd polecats/toast
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred
```
If clean: kill session, remove worktree, delete branch
If dirty: record failure, retry next cycle

**escalate**:
```bash
gt mail send mayor/ -s "Escalation: toast stuck" -m "..."
```

**none**: No action needed.

Record: action taken, result, updated nudge count.
Needs: decide

## Output

The arm completes with:
- action_taken: none | nudge-1 | nudge-2 | nudge-3 | killed | escalated
- result: success | failed | pending
- updated_state: New nudge count and timestamp for toast

This data feeds back to the parent patrol's aggregate step.
---
bonded_from: mol-polecat-arm
bonded_to: gt-f14c
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Missing space in error messages (handoff.go, prime.go)

Minor typo in error messages at two locations:

**handoff.go L895**:
```go
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon wisp" + protoID))
// Missing space before protoID
```

**prime.go L1061**:
Same issue.

**Fix**: Add space before protoID:
```go
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon wisp " + protoID))
```


verify-town-health

Final verification that Gas Town is healthy.

## Action
```bash
gt status
```

## Verify
1. Daemon running: Shows daemon status OK
2. Deacon active: Shows deacon in patrol mode
3. All witnesses: Each rig witness shows active
4. All refineries: Each rig refinery shows active

## OnStall
N/A - this is a read-only verification step.

## OnFail
Log degraded state but consider boot complete. Some agents may need manual recovery.
Run `gt doctor` for detailed diagnostics.


Merge: gt-h6eq.1

branch: polecat/nux
target: main
source_issue: gt-h6eq.1
rig: gastown


Test Patrol for Bonding

Parent issue for mol bond CLI test


Find abandoned work

Find abandoned work.

Scan for orphaned state:
- Issues marked in_progress with no active polecat
- Polecats that stopped responding mid-work
- Merge queue entries with no polecat owner
- Wisp sessions that outlived their spawner

```bash
bd list --status=in_progress
gt polecats --all --orphan
```

For each orphan:
- Check if polecat session still exists
- If not, mark issue for reassignment or retry
- File incident beads if data loss occurred


Digest: mol-deacon-patrol

Patrol 7: All healthy


Digest: mol-deacon-patrol

Patrol 2: archived stale Mayor handoffs, all agents healthy


Polecat template: simplify completion section to just 'gt done'

Completion section lists multiple options (gt done, gt handoff, bd sync). Should just say 'gt done' with succinct guidance on when bd sync is needed. Remove the alternatives that cause confusion.


Witness session cycling and handoff

Add session cycling and handoff protocol to Witness CLAUDE.md template.

## Session Cycling Protocol

```markdown
## Session Cycling

Your context will fill over long swarms. Proactively cycle when:
- Running for many hours
- Losing track of which workers you've checked
- Responses getting slower
- About to start complex operation

### Handoff Protocol

1. **Capture current state**:
```bash
town list .           # Worker states
town all beads        # Pending verifications
town inbox            # Unprocessed messages
```

2. **Compose handoff note**:
```
[HANDOFF_TYPE]: witness_cycle
[TIMESTAMP]: <now>
[RIG]: <rig>

## Active Workers
<list workers and status>

## Pending Verifications
<workers signaled done but not verified>

## Recent Actions
<last 3-5 actions>

## Warnings/Notes
<anything next session should know>

## Next Steps
<what should happen next>
```

3. **Send handoff**:
```bash
town mail send <rig>/witness -s "Session Handoff" -m "<note>"
```

4. **Exit cleanly**: End session, daemon spawns fresh one.

### On Fresh Session Start

1. Check for handoff: `town inbox | grep "Session Handoff"`
2. If found, read it and resume from handoff state
3. If not found, do full status check
```

## Implementation

Add to WITNESS_CLAUDE.md template.


Add agent abstraction layer to support non-Claude agents

Currently Gas Town hardcodes 'claude --dangerously-skip-permissions' throughout the codebase for spawning agents. We should add an abstraction layer to support other AI agents (e.g., Gemini CLI, OpenAI agents, local models).

Locations that spawn Claude:
- internal/cmd/mayor.go:131
- internal/cmd/deacon.go:150
- internal/cmd/witness.go:280
- internal/cmd/crew.go (multiple locations)
- internal/cmd/up.go:190, 229
- internal/session/manager.go:146
- internal/refinery/manager.go:207

Suggested approach:
1. Create an agent package with an interface
2. Add configuration for agent type in town/rig config
3. Replace hardcoded claude commands with agent.Spawn() calls
4. Support agents: claude, gemini, openai, local (ollama, etc.)


Check mail for MR submissions, escalations, messages.

```bash
gt mail inbox
# Process any urgent items
```

Handle shutdown requests, escalations, and status queries.

instantiated_from: mol-refinery-patrol
step: inbox-check


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously,
handling callbacks, monitoring rig health, and performing cleanup.
Each patrol cycle runs these steps in sequence, then loops or exits.


Remove all hardcoded gastown dependencies from gt codebase

The Go codebase should not have hardcoded dependencies on gastown (the rig name).

Found in prime.go outputDeaconPatrolContext() - FIXED in this session.

Other potential issues to audit:
- Check all patrol context functions (Witness, Refinery) for similar patterns
- Ensure rig-specific paths are derived from context, not hardcoded
- Test with a different rig name to verify

The principle: Gas Town should work with any rig name, not just gastown.


Swarm learning: Session cleanup missing from swarm workflow

## Problem

After Enders Game swarm completed (18 issues merged), 16 polecat sessions were left running but idle. No automated cleanup occurred.

## What Should Happen

1. Witness detects polecat completed work (idle at prompt)
2. Witness verifies git state is clean
3. Witness shuts down session
4. Witness reports completion to Mayor

## GGT Components

- gt-cxx: Witness context cycling (covers self-cycling)
- gt-u1j.9: Witness daemon heartbeat loop
- gt-kmn.6: Witness swarm landing protocol

## Recommendation

Add to Witness responsibilities:
- Monitor for 'work complete' signals (DONE keyword, idle detection)
- Automated session shutdown after verification
- Swarm completion reporting to Mayor

See also: architecture.md 'Worker Cleanup (Witness-Owned)' section which describes this but it wasn't implemented in PGT.


Engineer session restart protocol

Implement session restart flow for when the Engineer needs to split work:

1. Engineer creates subtask(s) in Beads assigned to self
2. Engineer sends handoff mail to self (🤝 HANDOFF)
3. Engineer sends restart request to Witness
4. Witness verifies:
   - Handoff mail exists in Engineer outbox/sent
   - Subtasks filed in Beads
5. Witness restarts the Refinery session (new Engineer context)

This enables "occasionally consistent, eventually convergent" work patterns.
The Refinery continues; the Engineer gets fresh context.


Digest: mol-deacon-patrol

Patrol 2: All healthy


Add harness overview to Mayor priming

Update gt prime Mayor context to explain the harness concept: umbrella repo for GT installation, rigs underneath, Mayor sits above all rigs


Digest: mol-deacon-patrol

Patrol complete: cleaned 1 orphaned process, all 8 sessions healthy, no stuck wisps


Digest: mol-deacon-patrol

Patrol 4: routine


gt mol command tree: status, catalog, burn, squash

Add gt mol subcommand as agent-side API for molecule operations.

Commands needed:
- gt mol status - What's on my hook? (pinned molecule, current step, progress)
- gt mol catalog - List available protos (delegate to bd mol catalog)
- gt mol burn - Burn current attachment
- gt mol squash - Squash current molecule to digest

This completes the agent-side API and makes the docs (sling-design.md, propulsion-principle.md) match reality.

Blocks: deacon.md.tmpl update (can't use gt mol status until it exists)


Add Gas Town theory of operation to all role primings

All roles (Mayor, Witness, Refinery, Polecat) should get basic GT architecture context: harness, rigs, agents, mail, beads workflow


Shutdown request handler

Handle polecat shutdown requests:

When polecat runs 'gt handoff --shutdown':
1. Polecat sends mail to <rig>/witness requesting shutdown
2. Witness receives mail
3. Witness verifies:
   - Git working tree is clean
   - Work is submitted (MR exists or in queue)
   - No uncommitted beads changes
4. If clean:
   - gt session stop <rig>/<polecat>
   - git worktree remove polecats/<name>
   - git branch -d polecat/<name>
5. If not clean:
   - Send nudge back to polecat
   - Track retry count

Depends on fixing gt-dsfi (handoff deadlock).


mol-polecat-arm

Single polecat inspection and action cycle.

This molecule is bonded dynamically by mol-witness-patrol's survey-workers step.
Each polecat being monitored gets one arm.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| polecat_name | Yes | Name of the polecat to inspect |
| rig | Yes | Rig containing the polecat |

## Steps

### capture
Capture recent tmux output for this polecat.

```bash
tmux capture-pane -t gt-{{rig}}-{{polecat_name}} -p | tail -50
```

Record:
- Last activity timestamp (when was last tool call?)
- Visible errors or stack traces
- Completion indicators ("Done", "Finished", etc.)

### assess
Categorize polecat state.

States:
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **requesting_shutdown**: Sent LIFECYCLE/Shutdown mail
- **done**: Showing completion indicators

Calculate: minutes since last activity.
Needs: capture

### load-history
Read nudge history for this polecat from patrol state.

```
nudge_count = state.nudges[{{polecat_name}}].count
last_nudge_time = state.nudges[{{polecat_name}}].timestamp
```

Needs: assess

### decide
Apply the nudge matrix to determine action.

| State | Idle Time | Nudge Count | Action |
|-------|-----------|-------------|--------|
| working | any | any | none |
| idle | <10min | any | none |
| idle | 10-15min | 0 | nudge-1 (gentle) |
| idle | 15-20min | 1 | nudge-2 (direct) |
| idle | 20+min | 2 | nudge-3 (final) |
| idle | any | 3 | escalate |
| error | any | any | assess-severity |
| requesting_shutdown | any | any | pre-kill-verify |
| done | any | any | pre-kill-verify |

Nudge text:
1. "How's progress? Need any help?"
2. "Please wrap up soon. What's blocking you?"
3. "Final check. Will escalate in 5 min if no response."

Record decision and rationale.
Needs: load-history

### execute
Take the decided action.

**nudge-N**:
```bash
tmux send-keys -t gt-{{rig}}-{{polecat_name}} "{{nudge_text}}" Enter
```

**pre-kill-verify**:
```bash
cd polecats/{{polecat_name}}
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred
```
If clean: kill session, remove worktree, delete branch
If dirty: record failure, retry next cycle

**escalate**:
```bash
gt mail send mayor/ -s "Escalation: {{polecat_name}} stuck" -m "..."
```

**none**: No action needed.

Record: action taken, result, updated nudge count.
Needs: decide

## Output

The arm completes with:
- action_taken: none | nudge-1 | nudge-2 | nudge-3 | killed | escalated
- result: success | failed | pending
- updated_state: New nudge count and timestamp

This data feeds back to the patrol's aggregate step.

Labels: [template, christmas-ornament, polecat-arm]


gt nudge should accept flexible session identifiers

Currently `gt nudge` requires the exact tmux session name (e.g., `gt-gastown-furiosa`).

It should also accept:
- `gastown/furiosa` (rig/polecat format)
- `furiosa` (polecat name, infer rig from cwd or require if ambiguous)

The session list command shows `gastown/furiosa` format, but nudge rejects it:
```
gt session list → shows 'gastown/furiosa'
gt nudge gastown/furiosa 'msg' → 'session not found'
gt nudge gt-gastown-furiosa 'msg' → works
```

Should normalize all these formats to the tmux session name internally.


Digest: mol-deacon-patrol

Patrol 2: Quiet cycle, all healthy, orphan gt-mol-aux persists


Digest: mol-deacon-patrol

Patrol cycle 3: all systems nominal


Digest: mol-deacon-patrol

P17: stable


Witness daemon: heartbeat loop, spawn ephemeral agent

Background daemon for agent lifecycle and monitoring.

## Core Responsibilities

1. **Heartbeat monitoring**: Check agent health periodically
2. **Session lifecycle**: Restart agents after handoff (Witness Protection)
3. **Polecat monitoring**: Track worker progress, nudging
4. **Escalation**: Report failures to Mayor

## Session Lifecycle (Witness Protection)

The daemon enables autonomous long-running operation by cycling agent sessions:

```go
type SessionLifecycle struct {
    AgentType string  // "witness", "refinery"
    StatePath string  // path to state.json
}

func (d *Daemon) monitorSessionLifecycle(agent SessionLifecycle) {
    // 1. Detect session exit
    // 2. Check state.json for requesting_cycle: true
    // 3. If cycle requested: start new session, clear flag
    // 4. If unexpected exit: escalate to Mayor
}
```

See architecture.md Key Decision #12: Agent Session Lifecycle.

## Interface

```go
type Daemon struct {
    rig      *Rig
    polecats *PolecatManager
    sessions *SessionManager
    config   DaemonConfig
}

type DaemonConfig struct {
    HeartbeatInterval time.Duration  // default: 30s
    NudgeThreshold    int            // nudges before escalation
    MaxWorkers        int            // from rig config
}

func NewDaemon(rig *Rig) *Daemon
func (d *Daemon) Start() error
func (d *Daemon) Stop() error

// Lifecycle
func (d *Daemon) CycleSession(agentType string) error
func (d *Daemon) SpawnWorker(issueID string) error
func (d *Daemon) ShutdownWorker(polecat string) error
```

## Heartbeat Loop

Every HeartbeatInterval:
1. Check Witness session (restart if cycle requested)
2. Check Refinery session (restart if cycle requested)
3. For each active polecat: assess progress, nudge if stuck
4. Query `bd ready` for new work, spawn up to max_workers


Failure handling: assign back to worker, add labels

Handle merge failures appropriately.

Failure types and actions:
| Failure     | Action                                      |
|-------------|---------------------------------------------|
| conflict    | Add needs-rebase label, assign to worker    |
| tests_fail  | Add needs-fix label, assign to worker       |
| build_fail  | Add needs-fix label, assign to worker       |
| flaky_test  | Retry once, then treat as tests_fail        |
| push_fail   | Retry with backoff, escalate if persistent  |

Actions:
1. bd update <id> --status=open --assignee=<worker>
2. bd update <id> --labels=<failure-label>
3. Send mail to worker explaining failure
4. Log failure details

Reference: docs/merge-queue-design.md#handling-failures


gt polecat remove --all: bulk polecat teardown

Currently gt polecat remove only accepts one polecat at a time. Need bulk operations:

## Requested
- `gt polecat remove gastown --all` - remove all polecats from a rig
- `gt polecat remove gastown/A gastown/B ...` - remove multiple by name

## Context
After a swarm completes, tearing down 20 polecats one at a time is tedious.
Ephemeral workers should be easy to create and destroy in bulk.

## Related
- gt-c92: CLI: all command for batch polecat operations


Digest: mol-deacon-patrol

Patrol 7: All agents healthy


test with labels


Merge: gt-t9u7

branch: polecat/furiosa
target: main
source_issue: gt-t9u7
rig: gastown


Polecat .beads/ contamination from stale branches

**Fixed in commit 8699b7b**

## Problem

When polecats are spawned from branches that previously had bd sync run on them, the .beads/ directory from the branch contains stale issues.jsonl, config.yaml, etc.

The setupSharedBeads() function was creating a redirect file, but NOT cleaning up the existing .beads/ contents first.

## Root Cause

1. Old polecat branch has .beads/ tracked in git (from previous bd sync)
2. gt spawn uses Add() which reuses existing branch
3. WorktreeAddExisting() checks out branch, including .beads/ files
4. setupSharedBeads() creates redirect, but other files remain
5. bd commands see stale data

## Fix

setupSharedBeads() now:
1. Removes entire .beads/ directory if it exists
2. Recreates fresh with only redirect file
3. Redirect points directly to mayor/rig/.beads (not through rig root)


Digest: mol-deacon-patrol

Patrol 14


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously,
handling callbacks, monitoring rig health, and performing cleanup.
Each patrol cycle runs these steps in sequence, then loops or exits.


MR: gt-test (main)

branch: main
target: main
source_issue: gt-test


Digest: mol-deacon-patrol @ 2025-12-24 19:48

Patrol 20: All healthy


mol-deacon-patrol


Activity Feed TUI

Terminal UI for browsing Gas Town activity. Shows hierarchical view of rigs, workers, and their current state. Features: live updates, expandable details, molecule progress (step X of Y). Built with bubbletea/lipgloss. Design doc: history/activity-feed-tui-design.md


Digest: mol-deacon-patrol

Patrol 8: Witnesses healthy


VM outpost setup: Terraform and documentation

## Overview

Documentation and optional Terraform for setting up VM outposts.

## Manual Setup Guide

```markdown
# Setting Up a VM Outpost

## Prerequisites
- GCE VM (or any Linux machine with SSH access)
- SSH key pair
- Git configured on VM

## Steps

1. Install Claude Code on VM:
   ```bash
   ssh user@vm
   npm install -g @anthropic-ai/claude-code
   ```

2. Clone Gas Town:
   ```bash
   mkdir -p ~/ai
   cd ~/ai
   gt install .
   ```

3. Configure Git credentials:
   ```bash
   git config --global user.name "Your Name"
   git config --global credential.helper store
   ```

4. Add outpost to local config:
   ```bash
   gt outpost add ssh \
     --name gce-burst \
     --host 10.0.0.5 \
     --user steve \
     --key ~/.ssh/gce_worker \
     --town-path /home/steve/ai \
     --max-workers 8
   ```

5. Test connectivity:
   ```bash
   gt outpost ping gce-burst
   ```
```

## Terraform Module (Optional)

```hcl
# deploy/terraform/vm-outpost/main.tf

variable "project" {}
variable "zone" { default = "us-central1-a" }
variable "machine_type" { default = "e2-standard-4" }

resource "google_compute_instance" "outpost" {
  name         = "gastown-outpost"
  machine_type = var.machine_type
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "ubuntu-2204-lts"
      size  = 100
    }
  }

  network_interface {
    network = "default"
    access_config {}
  }

  metadata_startup_script = file("${path.module}/startup.sh")
}

output "external_ip" {
  value = google_compute_instance.outpost.network_interface[0].access_config[0].nat_ip
}
```

## Files

- `docs/vm-outpost-setup.md`
- `deploy/terraform/vm-outpost/` (optional)

Depends on: gt-9a2.5 (SSHOutpost)


Digest: mol-deacon-patrol

Patrol #6: Routine


Test Patrol Parent

[RESURRECTED] This issue was deleted but recreated as a tombstone to preserve hierarchical structure.

Original description:
Test parent for Christmas Ornament pattern


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.


Digest: mol-deacon-patrol

Patrol 6: All healthy


Digest: mol-deacon-patrol

Patrol 8: All green


Digest: mol-deacon-patrol

Patrol 9: nominal


TIDY UP: Your previous work (patrol runner) was already m...

TIDY UP: Your previous work (patrol runner) was already merged to main. Check your git status is clean, sync beads, and if nothing to do, just run 'gt done'.


Workspace cleanup: preflight and postflight

Workspace preflight and postflight commands for clean state management.

## Preflight
```
gt preflight [--rig <rig>] [--dry-run]
```

Run before starting batch work:
1. Clean stale mail in inboxes
2. Check for stuck workers (warn)
3. Check rig health (polecats, refinery)
4. Verify git state is clean
5. Run bd sync to ensure beads current

## Postflight
```
gt postflight [--rig <rig>] [--archive-mail] [--dry-run]
```

Run after batch work completes:
1. Archive old mail with --archive-mail
2. Clean up stale integration branches
3. Sync beads
4. Report on rig state

## Implementation
```go
func Preflight(rigName string, dryRun bool) (*PreflightReport, error)
func Postflight(rigName string, opts PostflightOptions) (*PostflightReport, error)
```

## Report Structures
```go
type PreflightReport struct {
    MailCleaned    int
    RigHealthy     bool
    StuckWorkers   []string
    Warnings       []string
}

type PostflightReport struct {
    MailArchived   int
    BranchesCleaned int
    Warnings       []string
}
```

## Note

These are workspace maintenance commands, not tied to "swarm" lifecycle. Run them anytime to keep the rig clean.

## Acceptance Criteria
- [ ] Preflight cleans stale state
- [ ] Postflight archives old mail
- [ ] Both have --dry-run mode
- [ ] Clear reports of actions taken


Digest: mol-deacon-patrol

Patrol 15: All healthy


Execute registered plugins

Execute registered plugins.

Scan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with YAML frontmatter defining its gate (when to run) and instructions (what to do).

See docs/deacon-plugins.md for full documentation.

Gate types:
- cooldown: Time since last run (e.g., 24h)
- cron: Schedule-based (e.g., "0 9 * * *")
- condition: Metric threshold (e.g., wisp count > 50)
- event: Trigger-based (e.g., startup, heartbeat)

For each plugin:
1. Read plugin.md frontmatter to check gate
2. Compare against state.json (last run, etc.)
3. If gate is open, execute the plugin

Plugins marked parallel: true can run concurrently using Task tool subagents. Sequential plugins run one at a time in directory order.

Skip this step if ~/gt/plugins/ does not exist or is empty.


Obsolete beads issues need cleanup

Found obsolete issues that should be closed or fixed:

Test artifacts to close:
- gt-nriy: Test: Alpha to Beta (message test)
- gt-gswn: Integration test (test artifact)
- gt-54kn: Test: New Router

Broken dependencies (reference non-existent gt-test123):
- gt-vhby: implement
- gt-tvos: load-context
- gt-lwuu.2: implement (template variable unresolved)

CloudRun references (non-existent /deploy/cloudrun/):
- gt-9a2.6, gt-9a2.7, gt-9a2.11

Review and close/update these before launch.


Execute registered plugins


Digest: mol-deacon-patrol

Patrol 17: All clear


Polecat role references deprecated 'swarm' terminology

prompts/roles/polecat.md line 12 says:
'Part of a swarm: Other polecats may be working on related issues in parallel'

But architecture.md explicitly states:
'There are no swarm IDs - just epics with children'

The swarm concept has been replaced by streams/dependency model.
Update polecat.md to remove swarm references.


Digest: mol-deacon-patrol

Patrol #7: Stable


Check own context limit

Check own context limit.

The Deacon runs in a Claude session with finite context. Check if approaching the limit:

```bash
gt context --usage
```

If context is high (>80%), prepare for handoff:
- Summarize current state
- Note any pending work
- Write handoff to molecule state

This enables the Deacon to burn and respawn cleanly.


Digest: mol-deacon-patrol

Patrol 4: 9 sessions healthy


mol-deacon-patrol


Design molecule step hooks

Hooks that fire between molecule steps. When a bead in a molecule closes, trigger hook that can spawn agent attention to prompts/requests. This enables reactive orchestration - the molecule drives, hooks respond. Gas Town feature built on Beads data plane.


Merge: gt-3x1.5

branch: polecat/Immortan
target: main
source_issue: gt-3x1.5
rig: gastown


CLI: gt refinery commands (start, stop, status, queue)

CLI commands for managing the Refinery agent.

## Commands

```bash
gt refinery start <rig>      # Start refinery for a rig
gt refinery stop <rig>       # Stop refinery
gt refinery status <rig>     # Show refinery status
gt refinery queue <rig>      # Show merge queue
```

## gt refinery start

Starts the Refinery daemon for the specified rig.

Options:
- --foreground: Run in foreground (default: background)
- --auto-merge: Enable auto-merge (default: from config)

## gt refinery stop

Stops a running Refinery. Gracefully finishes current MR if processing.

## gt refinery status

Shows:
- Running state (running/stopped)
- Current MR being processed (if any)
- Queue length
- Last merge time
- Recent activity

## gt refinery queue

Shows the merge queue:
```
Merge queue for 'wyvern':
  1. [pending] Toast/polecat-auth-fix (15m ago)
  2. [pending] Capable/polecat-new-feature (5m ago)

1 merged today, 0 rejected
```

## Implementation

Uses gt-ov2 (Refinery agent) for daemon functionality.


Handle callbacks from agents

Handle callbacks from agents.

Check the Mayor's inbox for messages from:
- Witnesses reporting polecat status
- Refineries reporting merge results
- Polecats requesting help or escalation
- External triggers (webhooks, timers)

```bash
gt mail inbox
# For each message:
gt mail read <id>
# Handle based on message type
```

Callbacks may spawn new polecats, update issue state, or trigger other actions.


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

This proto enables nondeterministic idempotence for polecat work. A polecat that crashes after any step can restart, read its molecule state, and continue from the last completed step. No work is lost.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| issue | Yes | The source issue ID being worked on |


Digest: mol-deacon-patrol

Patrol #4: Stable


Digest: mol-deacon-patrol

Patrol #9


Merge: gt-99a

branch: polecat/Slit
target: main
source_issue: gt-99a
rig: gastown


ensure-deacon

Start the Deacon and verify patrol mode is active.

## Action
```bash
gt deacon start
```

## Verify
1. Session exists: `tmux has-session -t gt-deacon 2>/dev/null`
2. Not stalled: `gt peek deacon/` does NOT show "> Try" prompt
3. Heartbeat fresh: `deacon/heartbeat.json` modified < 2 min ago

## OnStall
```bash
gt nudge deacon/ "Start patrol."
sleep 30
# Re-verify
```

## OnFail
Log error and continue - town can run with degraded deacon.
The Witness can still manage polecats without Deacon oversight.


Fix out-of-sync molecule test expectations

Tests in builtin_molecules_test.go have hardcoded expectations that no longer match actual molecules:
- TestBuiltinMolecules: expects 9 molecules, got 11
- TestPolecatWorkMolecule: step refs out of sync
- TestDeaconPatrolMolecule: step count and refs out of sync

This is pre-existing on main, not introduced by any polecat work.


Digest: mol-deacon-patrol

Patrol 15: all quiet


Digest: mol-deacon-patrol

Patrol 9: All healthy


gt refinery attach: Attach to refinery session

Add 'gt refinery attach [rig]' command to attach to refinery tmux session.

Mirrors 'gt mayor attach' pattern. If rig not specified, use current rig context.


HTTP work server: gt worker serve command

## Overview

HTTP server that runs inside Cloud Run containers, accepting work requests.

## Command

```bash
gt worker serve --port 8080
```

## Implementation

```go
type WorkServer struct {
    port    int
    handler *WorkHandler
}

func (s *WorkServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    switch r.URL.Path {
    case "/work":
        s.handleWork(w, r)
    case "/health":
        s.handleHealth(w, r)
    default:
        http.NotFound(w, r)
    }
}

func (s *WorkServer) handleWork(w http.ResponseWriter, r *http.Request) {
    // 1. Parse WorkRequest
    // 2. Clone/pull repo
    // 3. Start Claude on issue
    // 4. Stream WorkEvents as NDJSON
    // 5. Return WorkResult
}
```

## Streaming Response

```go
func (s *WorkServer) streamEvents(w http.ResponseWriter, events <-chan WorkEvent) {
    flusher, _ := w.(http.Flusher)
    encoder := json.NewEncoder(w)
    for event := range events {
        encoder.Encode(event)
        flusher.Flush()
    }
}
```

## Files

- `internal/cloudrun/server.go`
- `cmd/gt/worker_serve.go` - Cobra command

## Dependencies

Depends on: gt-9a2.7 (protocol types)


Digest: mol-deacon-patrol

Patrol 15: Green


Update architecture documentation

Update all documentation to reflect refinery-as-worktree model.

## Files to update
- docs/architecture.md (if exists)
- CLAUDE.md references to refinery
- mayor/rig/docs/*.md - any refinery docs
- wisp-architecture.md - add MR wisp details
- README files mentioning clone vs worktree

## Key messages
- Refinery is worktree, not clone
- Polecat branches stay local
- Only main pushed to origin
- MRs are wisps (ephemeral)


Digest: mol-deacon-patrol @ 2025-12-24 19:46

Patrol 12: All healthy


Test: release command verification


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously,
handling callbacks, monitoring rig health, and performing cleanup.
Each patrol cycle runs these steps in sequence, then loops or exits.


Digest: mol-deacon-patrol

Patrol 18: Quiet


Enhanced polecat decommission prompting

Add decommission checklist to polecat AGENTS.md.template. Make crystal clear: verify ALL before signaling done.

## Checklist for AGENTS.md.template

```markdown
## Decommission Checklist

**CRITICAL**: Before signaling done, you MUST complete this checklist.
The Witness will verify each item and bounce you back if dirty.

### 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 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
```

### If Any Check Fails

- **Uncommitted changes**: Commit them or discard if 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
bd close <issue-id>
bd sync
town mail send <rig>/witness -s "Work Complete" -m "Issue <id> done."
```
```

## Implementation

Add to AGENTS.md.template in the polecat prompting section.


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

This molecule is bonded dynamically by mol-witness-patrol's survey-workers step.
Each polecat being monitored gets one arm that runs in parallel with other arms.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| polecat_name | Yes | Name of the polecat to inspect |
| rig | Yes | Rig containing the polecat |

## Step: capture
Capture recent tmux output for toast.

```bash
tmux capture-pane -t gt-gastown-toast -p | tail -50
```

Record:
- Last activity timestamp (when was last tool call?)
- Visible errors or stack traces
- Completion indicators ("Done", "Finished", etc.)

## Step: assess
Categorize polecat state based on captured output.

States:
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **requesting_shutdown**: Sent LIFECYCLE/Shutdown mail
- **done**: Showing completion indicators

Calculate: minutes since last activity.
Needs: capture

## Step: load-history
Read nudge history for toast from patrol state.

```
nudge_count = state.nudges[toast].count
last_nudge_time = state.nudges[toast].timestamp
```

This data was loaded by the parent patrol's load-state step and passed
to the arm via the bonding context.
Needs: assess

## Step: decide
Apply the nudge matrix to determine action for toast.

| State | Idle Time | Nudge Count | Action |
|-------|-----------|-------------|--------|
| working | any | any | none |
| idle | <10min | any | none |
| idle | 10-15min | 0 | nudge-1 (gentle) |
| idle | 15-20min | 1 | nudge-2 (direct) |
| idle | 20+min | 2 | nudge-3 (final) |
| idle | any | 3 | escalate |
| error | any | any | assess-severity |
| requesting_shutdown | any | any | pre-kill-verify |
| done | any | any | pre-kill-verify |

Nudge text:
1. "How's progress? Need any help?"
2. "Please wrap up soon. What's blocking you?"
3. "Final check. Will escalate in 5 min if no response."

Record decision and rationale.
Needs: load-history

## Step: execute
Take the decided action for toast.

**nudge-N**:
```bash
tmux send-keys -t gt-gastown-toast "{{nudge_text}}" Enter
```

**pre-kill-verify**:
```bash
cd polecats/toast
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred
```
If clean: kill session, remove worktree, delete branch
If dirty: record failure, retry next cycle

**escalate**:
```bash
gt mail send mayor/ -s "Escalation: toast stuck" -m "..."
```

**none**: No action needed.

Record: action taken, result, updated nudge count.
Needs: decide

## Output

The arm completes with:
- action_taken: none | nudge-1 | nudge-2 | nudge-3 | killed | escalated
- result: success | failed | pending
- updated_state: New nudge count and timestamp for toast

This data feeds back to the parent patrol's aggregate step.
---
bonded_from: mol-polecat-arm
bonded_to: gt-na7y
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Town Doctor molecule for harness health checks

Create a Town Doctor molecule that any Gas Town agent can run to diagnose and repair harness issues.

## Concept

Instead of just `gt doctor` as a CLI command with hardcoded checks, create a **molecule** (checklist workflow) that:
- Any agent (Mayor, Witness, Polecat) can instantiate
- Walks the agent through diagnostic steps
- Agent uses judgment to fix issues found
- Works as a structured troubleshooting guide

## Why a Molecule?

1. **Agent-driven**: The agent running it becomes "the doctor" temporarily
2. **Extensible**: Add new checks by updating the molecule, not code
3. **Contextual**: Agent can reason about issues, not just run scripts
4. **Self-healing**: Agent can fix problems it finds, not just report them

## Proposed Checks (molecule steps)

1. Verify harness structure (mayor/, .beads/, CLAUDE.md exist)
2. Validate config files (town.json, rigs.json parse correctly)
3. Check beads health (bd doctor, redirect validity)
4. Verify git state (clean working tree, proper remotes)
5. Check rig integrity (each registered rig exists, has config.json)
6. Validate agent clones (mayor/rig/, refinery/rig/ exist and are valid)
7. Check for orphaned worktrees/branches
8. Verify daemon state (if running)

## Integration

- `gt doctor` could instantiate the molecule for the current agent
- Or agent can run `bd ready` and pick up doctor tasks when prioritized
- Results logged to beads for audit trail

## Related

- gt-cr9: Harness Design & Documentation (completed)
- Molecules design in architecture.md


Digest: mol-deacon-patrol

Patrol 3: nux exited (wrong-rig escalation), 11 sessions, all core healthy


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 19: routine


Protocol message specification

Define YAML format for protocol messages. Subject: [PROTOCOL_TYPE] brief. Body: structured payload. Document all protocol types: POLECAT_READY, MERGE_SUCCESS, MERGE_FAILED, REWORK_REQUEST, WORK_COMPLETE, NEED_HELP, ESCALATION.


Digest: mol-deacon-patrol

Patrol 7: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol 4: routine checks all clear


gt spawn: Notify Deacon and Witness on polecat start

When gt spawn creates a polecat, it should mail both Deacon and Witness:

```
gt mail send <rig>/witness -s 'POLECAT_STARTED furiosa' -m 'Issue: gt-xxx'
gt mail send deacon/ -s 'POLECAT_STARTED gastown/furiosa' -m 'Issue: gt-xxx'
```

This enables:
- Witness to bond a lease to its patrol wisp
- Deacon to verify worker started (redundancy)
- Both to nudge if worker is idle at prompt

Part of the village self-monitoring architecture.


Prevent aspect self-matching (infinite recursion)

Aspects should only match original steps, not steps inserted by the same aspect application. Document this and implement guard during cooking. Without this, a pointcut like *.implement that inserts security-prescan could match its own insertion infinitely.


Digest: mol-deacon-patrol

P12: stable


Add gt crew rename command


Add multi-lang-shiny example and tests

Create example meta-formula and test suite.

## Example

Create .beads/formulas/multi-lang-shiny.meta.yaml:
- Generates shiny-go, shiny-python, shiny-typescript
- Each extends base-shiny with language-specific vars

## Tests

1. Test basic expansion (3 languages -> 3 formulas)
2. Test variable substitution in names and content
3. Test error on duplicate generated names
4. Test empty values list
5. Integration: cook a generated formula


Test Patrol Parent

Test parent for Christmas Ornament pattern


README missing prerequisites section (tmux required)

The README.md does not mention that tmux is required.
All agent sessions use tmux, but fresh users have no way to know this.

Add prerequisites section:
- Go 1.23+
- Git
- tmux (required for agent sessions)
- Claude Code CLI (for agents)


Phase 2: Quiescent agents (Witness, Refinery)

Enable Witness and Refinery to sleep until triggered.

## Scope
- Wake triggers: gt spawn, MR submit, mail, Deacon ping
- Wake SLA: <1 minute
- mol-witness-patrol and mol-refinery-patrol definitions
- Quiescent entry/exit protocol

## Implementation
- Kill tmux session on quiescent entry
- Preserve sandbox (worktree, state files)
- Restart session on wake trigger
- Agent checks pinned, spawns default patrol if naked

Depends: Phase 1 complete


Doctor check: Worker health and stuck detection

Detect and report stuck workers via gt doctor.

## Checks

### WorkerHealthCheck
- List all active workers (polecats with state=working)
- Check last activity timestamp for each
- Flag as potentially stuck if no progress for configurable threshold (default: 30 min)
- Check if Witness is running for the rig
- Verify Witness last heartbeat time

### Stuck Detection Criteria
- Polecat state=working but session not running
- Polecat state=working but output unchanged for threshold
- Witness not responding to health checks
- Multiple polecats in same rig all stuck

## Output

```
[WARN] Workers in rig 'wyvern' may be stuck:
  - Toast: working for 45m, no recent output
  - Capable: working for 52m, session not found
  - Witness: last heartbeat 20m ago

  Suggestions:
  - gt witness status wyvern
  - gt capture wyvern/Toast 50
  - gt stop --rig wyvern (kill all)
```

## Auto-Fix

Cannot auto-fix stuck workers (risk of data loss), but can:
- Restart Witness daemon if crashed
- Send warning mail to Mayor


Digest: mol-deacon-patrol

Patrol cycle 10: nominal


Digest: mol-deacon-patrol

Patrol 9: All healthy, no messages


Digest: mol-deacon-patrol

Patrol 8: nominal


Digest: mol-deacon-patrol

Patrol 5


bd mol install: Install formula from GitHub

Fetch and install a formula from a GitHub repository.

Usage: bd mol install github.com/org/repo[@version]

Should:
- Clone/fetch the formula.json from the repo
- Validate the formula structure
- Store in local catalog
- Track installation in .beads/installed.json


Digest: mol-deacon-patrol

Patrol 18: nominal


Clean dead sessions

Clean dead sessions.

Garbage collect terminated sessions:
- Remove stale polecat directories
- Clean up wisp session artifacts
- Prune old logs and temp files
- Archive completed molecule state

```bash
gt gc --sessions
gt gc --wisps --age=1h
```

Preserve audit trail. Only clean sessions confirmed dead.


Add 'gt account default' command

Set the default account in accounts.yaml. Used when no GT_ACCOUNT env or --account flag specified.


ApplyBranches/ApplyGates mutate steps in place

ApplyBranches and ApplyGates claim to return a modified steps slice, but they actually mutate the original steps via the pointer map from buildStepMap().

```go
// ApplyBranches docstring says:
// Returns the modified steps slice (steps are modified in place for dependencies).
```

This is technically documented but violates the pattern established by ApplyLoops and ApplyAdvice which return new step slices.

Options:
1. Document explicitly that these functions mutate in place (current behavior)
2. Clone steps before modification for true immutability
3. Accept this as intentional since it's an optimization

The current behavior is safe because cook.go doesn't reuse the input slice, but could cause subtle bugs if callers expect immutability.

Recommend option 1 (document) or 2 (clone) for consistency.


Digest: mol-deacon-patrol

Patrol cycle 2: all healthy, no action required


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.


Daemon: configurable heartbeat interval

Heartbeat interval is hardcoded to 60s. Should be configurable via:
- town.json config
- Command line flag
- Environment variable

Default 60s is reasonable but some deployments may want faster/slower.


gt sling reports hook occupied but bd hook shows empty

gt sling thinks a hook is occupied when bd hook shows it empty. Example: bd hook --agent beads/crew/dave shows (empty), but gt sling bd-hobo beads/crew/dave says 'hook already occupied by bd-ul59'. They should use the same source of truth (beads database pinned field).


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously,
handling callbacks, monitoring rig health, and performing cleanup.
Each patrol cycle runs these steps in sequence, then loops or exits.


mol-deacon-patrol


CLI: session commands (start, stop, at, list, capture, inject)

Session management CLI commands.

## Commands

### gt session start
Start a polecat session.
```
gt session start <rig>/<polecat> [--issue <id>]
```
- Creates tmux session
- Launches claude in polecat workdir
- Optionally injects initial issue context

### gt session stop
Stop a polecat session.
```
gt session stop <rig>/<polecat> [--force]
```
- Graceful shutdown by default
- --force kills immediately

### gt session at (attach)
Attach to running session.
```
gt session at <rig>/<polecat>
```
- Attaches tmux session to current terminal
- Detach with Ctrl-B D

### gt session list
List all sessions.
```
gt session list [--rig <rig>] [--json]
```
- Shows running/stopped status
- Optionally filter by rig

### gt session capture
Capture recent output from session.
```
gt session capture <rig>/<polecat> [--lines <n>]
```
- Default: last 100 lines
- Useful for checking polecat progress

### gt session inject
Send message to session.
```
gt session inject <rig>/<polecat> -m "message"
gt session inject <rig>/<polecat> -f <file>
```
- Injects text via tmux send-keys
- Used for nudges, notifications

## Address Format

`<rig>/<polecat>` e.g., `wyvern/Toast`

## Implementation

Session subcommand group:
```go
var sessionCmd = &cobra.Command{Use: "session"}
sessionCmd.AddCommand(startCmd, stopCmd, atCmd, listCmd, captureCmd, injectCmd)
```


Policy beads: config in data plane

Use sentinel/policy beads for configuration instead of external config. Examples: daemon notifications on/off, heartbeat intervals. Config lives in the bead graph, can be toggled by closing/opening policy beads.


Self-review

Review your own changes. Look for:
- Bugs and edge cases
- Style issues
- Missing error handling
- Security concerns

Fix any issues found before proceeding.


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

This proto enables nondeterministic idempotence for polecat work. A polecat that crashes after any step can restart, read its molecule state, and continue from the last completed step. No work is lost.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| issue | Yes | The source issue ID being worked on |


Prompt templates: role contexts, nudge messages

Prompt templates for role contexts and messages.

## Template Types

### Role CLAUDE.md Templates

For gt prime and CLAUDE.md generation:
- Mayor template
- Witness template
- Refinery template
- Polecat template

### Message Templates

For notifications and nudges:
- Spawn assignment
- Witness nudge
- Escalation to Mayor
- Session handoff

## Implementation

```go
//go:embed templates/*.md.tmpl
var templateFS embed.FS

type Templates struct {
    fs embed.FS
}

func NewTemplates() *Templates
func (t *Templates) RenderRole(role string, data RoleData) (string, error)
func (t *Templates) RenderMessage(name string, data any) (string, error)
```

## Template Data

```go
type RoleData struct {
    Role      string
    RigName   string
    TownRoot  string
    Polecats  []string
    Commands  []CommandHelp
}

type SpawnData struct {
    Issue       string
    Title       string
    Priority    int
    Description string
}

type NudgeData struct {
    Polecat    string
    Reason     string
    NudgeCount int
    MaxNudges  int
}
```

## Template Location

Embedded in binary via go:embed:
```
internal/templates/
├── roles/
│   ├── mayor.md.tmpl
│   ├── witness.md.tmpl
│   ├── refinery.md.tmpl
│   └── polecat.md.tmpl
└── messages/
    ├── spawn.md.tmpl
    ├── nudge.md.tmpl
    └── escalation.md.tmpl
```

## Usage

gt prime uses role templates.
gt spawn uses spawn template.
Witness uses nudge/escalation templates.


bd create --dedup: semantic deduplication before issue creation

Before creating issue, check for semantic duplicates using AI similarity.

**From VC**: internal/deduplication/ - AI-powered batch comparison. ~300 lines.
VC had issue pollution problem: 438 issues with ~350+ spam because no early dedup.

**Gas Town implementation**: CLI flag on bd create:
```bash
bd create --dedup --title="Fix auth bug" --description="..."
```

Checks recent issues (7-day window) with AI similarity. If confidence >0.85, warns or blocks.

**Value**: Prevents pollution from parallel workers discovering same issues.

**VC lesson**: 115 issues filed in single day (Nov 2) because supervisor over-discovered without dedup. Rate limiting + dedup are essential.


Add gate timeout tracking and notification

Implement timeout and notification logic for gates.

## Timeout Behavior
1. Gate created with timeout (e.g., 30m)
2. Deacon tracks elapsed time during patrol
3. If timeout reached:
   - Notify all waiters: 'Gate timed out'
   - Close gate with timeout reason
   - Waiter can retry, escalate, or fail gracefully

## Notification
- Use gt mail send to notify waiters
- Include gate ID, await type, and reason in message
- Support multiple waiters notification

## Moved from beads
Originally bd-ykqu. Gate notifications are Deacon's job in gastown.


Digest: mol-deacon-patrol

P7: escalation for mayor (wrong-rig work)


Digest: mol-deacon-patrol

Patrol 12: nominal


Digest: mol-deacon-patrol

Patrol #2: Routine - all 6 agents healthy


Implement/document gt sling mechanism

Investigate and implement the gt sling command for attaching molecules to crew workers. Check if gt sling exists, design the flow (mail-based vs direct pin vs wisp spawn), implement in gastown CLI, integrate with bd mol/wisp/pin commands.


Digest: mol-deacon-patrol @ 2025-12-24 19:44

Patrol 5: All healthy


Digest: mol-deacon-patrol

Patrol 19: Green


Role prompts have mismatched startup protocols

Different role prompts describe different startup protocols:

- deacon.md: Check gt mol status, spawn if none: bd mol spawn
- refinery.md: Check bd list --status=in_progress, bond if none: gt mol bond
- polecat.md: Check bd mol current

These should use consistent terminology and commands.
The propulsion principle should be applied uniformly.


Digest: mol-deacon-patrol


Implement

Implement the solution for gt-8tmz.34. Follow codebase conventions.
File discovered work as new issues with bd create.

Make regular commits with clear messages.
Keep changes focused on the assigned issue.


Create mol-gastown-polecat derived molecule

Create the standard Gas Town polecat workflow molecule.

## Molecule Definition
\`\`\`markdown
## Molecule: gastown-polecat
Full workflow for Gas Town polecats including binary installation.

Includes: mol-engineer-in-box

## Step: install-binary
After merge is submitted, rebuild and install the local gt binary.
This ensures the latest code is available to all local agents.

Run from the rig directory:
\`\`\`
go build -o gt ./cmd/gt
go install ./cmd/gt
\`\`\`

Needs: submit
\`\`\`

## Why This Molecule
Every polecat that pushes to main should also rebuild the binary.
This ensures the installed gt is always current with main.

## Implementation
1. Add to builtin_molecules.go (after Includes support lands)
2. Update SeedBuiltinMolecules
3. Run gt molecule seed

## Acceptance
- [ ] mol-gastown-polecat exists
- [ ] Includes all engineer-in-box steps
- [ ] Adds install-binary step after submit
- [ ] Can be used with gt spawn --molecule


Digest: mol-deacon-patrol

Patrol 20: routine, handing off


Digest: mol-deacon-patrol

Patrol 16


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 9: clear


Witness handoff bead state persistence

Implement state persistence for Witness across wisp cycles.

## Problem
Wisps burn between cycles, but Witness needs to remember:
- Which workers have been nudged
- How many times (nudge_count)
- When was last nudge
- Last observed activity

## Solution
Witness handoff bead with worker_states field:

```json
{
  "id": "gt-witness-state",
  "type": "handoff",
  "assignee": "<rig>/witness",
  "pinned": true,
  "worker_states": {
    "furiosa": {
      "issue": "gt-123",
      "nudge_count": 2,
      "last_nudge": "2024-12-22T10:00:00Z"
    }
  },
  "last_patrol": "2024-12-22T10:05:00Z"
}
```

## Implementation
1. On patrol start: bd show <witness-handoff-id> to load state
2. During patrol: update in-memory state
3. On save-state step: bd update to persist
4. State survives wisp burn/squash

## Depends on
- gt-83k0 (mol-witness-patrol definition)


Worker cleanup: Beads sync on shutdown

Add beads sync verification to worker cleanup checklist and Witness verification.

## Update to Decommission Checklist (gt-sd6)

Add to pre-done verification:
- bd sync --status must show 'Up to date'
- git status .beads/ must show no changes

## Beads Edge Cases

Uncommitted beads changes:
  bd sync
  git add .beads/
  git commit -m 'beads: final sync'

Beads sync conflict (rare):
  git fetch origin main
  git checkout main -- .beads/
  bd sync --force
  git add .beads/
  git commit -m 'beads: resolve sync conflict'

## Update to Witness Verification (gt-f8v)

When capturing worker state:
  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, nudge:
  WITNESS CHECK: Beads not synced. Run 'bd sync' then commit .beads/. Signal done when complete.


Digest: mol-deacon-patrol

Patrol 12: All healthy, no messages


Phase 3.1: Summary generation protocol

Define how agents generate summaries for squash.

## The Problem

Beads doesn't make AI calls (inversion of control). Gas Town agents must:
1. Generate their own summary before calling squash
2. Pass summary to bd squash command

## Summary Template

```
Task: <source issue title>
Action: <what was done - fix/implement/refactor/etc>
Outcome: <result - tests pass, committed, needs follow-up, etc>
Details: <1-2 sentences of specifics if needed>
```

## Example

```
Task: Fix lifecycle parser matching bug (gt-rixa)
Action: Reordered conditional checks in parseLifecycleRequest
Outcome: Tests passing, committed to polecat/furiosa
Details: The 'cycle' keyword was matching 'lifecycle:' prefix. Now checks restart/shutdown first, uses word boundary for cycle.
```

## Command

```bash
bd squash eph-abc123 --summary "Task: Fix lifecycle parser..."
```


Rename .beads-ephemeral to .beads-wisps in docs

The wisp storage directory should be named `.beads-wisps/` not `.beads-ephemeral/`.

Also fix the architecture: Witness and Refinery share mayor/rig's beads and wisps.
They don't have separate ephemeral stores.

## Files to update
- docs/wisp-architecture.md
- docs/architecture.md
- ~/gt/docs/patrol-system-design.md
- ~/gt/CLAUDE.md

## Changes
1. Rename `.beads-ephemeral/` → `.beads-wisps/` everywhere
2. Remove incorrect references to witness/.beads-ephemeral/ and refinery/rig/.beads-ephemeral/
3. Clarify that all rig-level patrols use mayor/rig/.beads-wisps/


Digest: mol-deacon-patrol

Patrol #16: Stable


Digest: mol-deacon-patrol

Patrol 16: routine


Digest: mol-deacon-patrol

Patrol 17


Digest: mol-deacon-patrol

Patrol 20: All healthy - handoff threshold reached


Digest: mol-deacon-patrol

Patrol 9: Quiet


Town root .beads has schema mismatch with bd

The .beads directory at town root (/Users/stevey/gt/.beads) has an incompatible schema:

```
Error: failed to open database: failed to initialize schema: sqlite3: SQL logic error: no such column: thread_id
```

Meanwhile, gastown/.beads (symlinked to mayor/rig/.beads) works fine.

## Impact

- gt mail inbox fails at town root
- gt handoff sends mail to broken db
- Daemon can't check its inbox

## Options

1. Delete town root .beads/beads.db and let it recreate
2. Symlink town root .beads to gastown/.beads
3. Run schema migration on existing db

## Root Cause

Likely a beads version upgrade that added thread_id column, but the town root db was created before that.


Refinery Engineer: Role prompting and CLAUDE.md

Create refinery/CLAUDE.md with Chief Merge Engineer role context. Include:
- Role identity and responsibilities
- Decision authority (merge order, test frequency, binary rebuilds)
- Communication patterns (Witness, Deacon)
- Session lifecycle (handoff bead protocol)
- Key commands reference


gt prime should detect mayor role from any rig's mayor/ folder

Currently gt prime only detects the Mayor role when run from town root (~/gt). It should also detect Mayor when run from:
- ~/gt/gastown/mayor/rig (rig's internal mayor dir)
- Any path containing /mayor/ under a rig

This would allow the mayor session to work correctly regardless of which rig directory it's attached to.


CLI: polecat commands (add, list, wake, sleep, decommission)

GGT is missing most polecat management commands that PGT has.

Missing Commands:
- gt polecat add <rig> <name> - Add polecat to rig (creates clone)
- gt polecat list [<rig>] - List polecats with state
- gt polecat info <polecat> - Show detailed info
- gt polecat wake <polecat> - Mark available
- gt polecat sleep <polecat> - Mark unavailable
- gt polecat decommission <polecat> - Remove polecat safely

PGT Reference: gastown-py/src/gastown/cli/polecat_cmd.py

Notes:
- spawn exists but doesn't cover management
- wake/sleep are in polecat manager but not CLI
- decommission should check for uncommitted work


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

This molecule is bonded dynamically by mol-witness-patrol's survey-workers step.
Each polecat being monitored gets one arm that runs in parallel with other arms.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| polecat_name | Yes | Name of the polecat to inspect |
| rig | Yes | Rig containing the polecat |

## Step: capture
Capture recent tmux output for toast.

```bash
tmux capture-pane -t gt-gastown-toast -p | tail -50
```

Record:
- Last activity timestamp (when was last tool call?)
- Visible errors or stack traces
- Completion indicators ("Done", "Finished", etc.)

## Step: assess
Categorize polecat state based on captured output.

States:
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **requesting_shutdown**: Sent LIFECYCLE/Shutdown mail
- **done**: Showing completion indicators

Calculate: minutes since last activity.
Needs: capture

## Step: load-history
Read nudge history for toast from patrol state.

```
nudge_count = state.nudges[toast].count
last_nudge_time = state.nudges[toast].timestamp
```

This data was loaded by the parent patrol's load-state step and passed
to the arm via the bonding context.
Needs: assess

## Step: decide
Apply the nudge matrix to determine action for toast.

| State | Idle Time | Nudge Count | Action |
|-------|-----------|-------------|--------|
| working | any | any | none |
| idle | <10min | any | none |
| idle | 10-15min | 0 | nudge-1 (gentle) |
| idle | 15-20min | 1 | nudge-2 (direct) |
| idle | 20+min | 2 | nudge-3 (final) |
| idle | any | 3 | escalate |
| error | any | any | assess-severity |
| requesting_shutdown | any | any | pre-kill-verify |
| done | any | any | pre-kill-verify |

Nudge text:
1. "How's progress? Need any help?"
2. "Please wrap up soon. What's blocking you?"
3. "Final check. Will escalate in 5 min if no response."

Record decision and rationale.
Needs: load-history

## Step: execute
Take the decided action for toast.

**nudge-N**:
```bash
tmux send-keys -t gt-gastown-toast "{{nudge_text}}" Enter
```

**pre-kill-verify**:
```bash
cd polecats/toast
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred
```
If clean: kill session, remove worktree, delete branch
If dirty: record failure, retry next cycle

**escalate**:
```bash
gt mail send mayor/ -s "Escalation: toast stuck" -m "..."
```

**none**: No action needed.

Record: action taken, result, updated nudge count.
Needs: decide

## Output

The arm completes with:
- action_taken: none | nudge-1 | nudge-2 | nudge-3 | killed | escalated
- result: success | failed | pending
- updated_state: New nudge count and timestamp for toast

This data feeds back to the parent patrol's aggregate step.
---
bonded_from: mol-polecat-arm
bonded_to: gt-kgk5
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Daemon patrol should clean stale locks

The gt daemon patrol cycle should detect and clean up stale locks.

## Problem
If daemon crashes or there are orphaned locks, they can block operations indefinitely.

## Proposed Solution
During patrol cycle:
1. Check for lock files older than threshold (e.g., 5 minutes)
2. Verify owning process is dead (check PID if stored)
3. Remove stale locks
4. Log cleanup for audit


Digest: mol-deacon-patrol

P7: stable


Digest: mol-deacon-patrol

Patrol 5: Routine


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously,
handling callbacks, monitoring rig health, and performing cleanup.
Each patrol cycle runs these steps in sequence, then loops or exits.


Digest: mol-deacon-patrol

Patrol #7


Digest: mol-deacon-patrol

Patrol 6: routine


gt mq integration status: show integration branch status

Implement 'gt mq integration status <epic>' command.

Display:
- Integration branch name and creation date
- Commits ahead of main
- MRs merged to integration (closed)
- MRs pending (open, targeting integration)
- Comparison: main..integration/<epic>

Output example:
  Integration: integration/gt-auth-epic
  Created: 2025-12-17
  Ahead of main: 5 commits

  Merged MRs (3):
    gt-mr-001  Fix login timeout
    gt-mr-002  Fix session expiry
    gt-mr-003  Update auth config

  Pending MRs (1):
    gt-mr-004  Update auth tests (in_progress)

Reference: docs/merge-queue-design.md#integration-branches


TODO: Check if issue is child of configured epic in Witness

witness/manager.go:688 has a TODO to filter issues by whether they're children of the configured epic. Currently this filter is skipped.


Add audit trail for hook detach operations

Log detachment events for debugging and monitoring.

When work is detached from hook:
- Log timestamp, agent, molecule ID, reason
- If abnormal (not completion), notify Witness
- Consider adding to wisp digest for patrol cycles


Digest: mol-deacon-patrol

Patrol 3: Quick scan, stable


Digest: mol-deacon-patrol

Patrol 11: All healthy


Digest: mol-deacon-patrol

Patrol 12: routine


Switch formulas from JSON to TOML

## Problem
Formula JSON files have poor ergonomics for agents and humans:
- Multi-line strings require `\n` escaping
- Diffs are hard to read (long single-line changes)
- No comments allowed

## Solution
Switch formulas to TOML format:

```toml
formula = "mol-deacon-patrol"
version = 1
description = """
Mayor's daemon patrol loop.
Multi-line strings work naturally.
"""

[[steps]]
id = "inbox-check"
title = "Handle callbacks"
description = """
Check inbox for messages.

```bash
gt mail inbox
```
"""
```

## Tasks
- [ ] Add TOML parsing for formulas (github.com/BurntSushi/toml)
- [ ] Update formula loader to try .toml first, fall back to .json
- [ ] Add `bd formula convert <name>` to migrate JSON → TOML
- [ ] Convert existing formulas
- [ ] Update docs

## Notes
- Keep issues.jsonl as-is (machine data, append-only)
- TOML only for human-edited formula files


mol-witness-patrol

Per-rig worker monitor patrol loop using the Christmas Ornament pattern.

The Witness is the Pit Boss for your rig. You watch polecats, nudge them toward
completion, verify clean git state before kills, and escalate stuck workers.

**You do NOT do implementation work.** Your job is oversight, not coding.

## The Christmas Ornament Shape

This molecule uses dynamic bonding to create inspection arms per-polecat:

```
                    ★ mol-witness-patrol (trunk)
                   /|\
            ┌─────┘ │ └─────┐
         PREFLIGHT DISCOVERY CLEANUP
            │       │        │
        ┌───┴───┐ ┌─┴─┐  ┌───┴───┐
        │inbox  │ │sur│  │aggreg │
        │refnry │ │vey│  │save   │
        │load   │ └─┬─┘  │summary│
        └───────┘   │    │contxt │
                    │    │loop   │
          ┌─────────┼─────────┐ └───────┘
          │         │         │
          ●         ●         ●     mol-polecat-arm (dynamic)
         ace       nux      toast
          │         │         │
       ┌──┴──┐   ┌──┴──┐   ┌──┴──┐
       │cap  │   │cap  │   │cap  │
       │ass  │   │ass  │   │ass  │
       │dec  │   │dec  │   │dec  │
       │exec │   │exec │   │exec │
       └──┬──┘   └──┬──┘   └──┬──┘
          │         │         │
          └─────────┴─────────┘
                    │
                 ⬣ base (cleanup)
```

## Phases

### PREFLIGHT (fixed steps)
1. inbox-check - Process lifecycle requests, help messages
2. check-refinery - Ensure MQ is alive and processing
3. load-state - Read persistent state (nudge counts, etc.)

### DISCOVERY (spawns dynamic arms)
4. survey-workers - List polecats, bond mol-polecat-arm per polecat
5. run-plugins - Bond mol-plugin-runner for each witness plugin

### CLEANUP (gate + fixed steps)
6. aggregate - GATE: WaitsFor all arms + plugins to complete
7. save-state - Persist nudge counts, action log
8. generate-summary - Create digest content
9. context-check - Check if context is high
10. burn-or-loop - Squash/burn wisp, then loop or exit

## Dynamic Arms

Each polecat gets mol-polecat-arm bonded as a wisp child:
- capture - Capture tmux output
- assess - Categorize state (working/idle/error/done)
- load-history - Get nudge counts for this polecat
- decide - Apply nudge matrix
- execute - Take action (nudge/kill/escalate/none)

Arms run in PARALLEL. The aggregate step waits for all to complete.

## Activity Feed

This design enables real-time visibility:

```
[14:32:08] + patrol-x7k.arm-ace bonded (5 steps)
[14:32:09] → patrol-x7k.arm-ace.capture in_progress
[14:32:10] ✓ patrol-x7k.arm-ace.capture completed
[14:32:14] ✓ patrol-x7k.arm-ace.decide completed (action: nudge-1)
[14:32:17] ✓ patrol-x7k.arm-ace COMPLETE
```

## Storage

- Wisp storage: .beads-wisp/ (ephemeral, gitignored)
- Persistent state: witness handoff bead (nudge counts, etc.)
- Digests: Squashed summaries in permanent beads

## Dependencies

- bd-xo1o: Dynamic Molecule Bonding epic (in beads rig)
  - bd mol bond with variable substitution
  - WaitsFor directive for fanout gates
  - Activity feed query

Labels: [template, christmas-ornament]


load-context

Run gt prime and bd prime. Verify issue assignment.
Check inbox for any relevant messages.

Read the assigned issue (gt-qwyu) and understand the requirements.
Identify any blockers or missing information.


Digest: mol-deacon-patrol

Patrol 18: All healthy


Digest: mol-deacon-patrol

Patrol 3: All healthy, routine


stderr suppression hides critical errors

Multiple files set cmd.Stderr = nil:
- prime.go
- up.go
- orphans.go
- daemon.go

This hides git errors and command failures.

Should capture stderr for debugging and log when errors occur,
rather than suppressing entirely.


Digest: mol-deacon-patrol

Patrol 2: All clear


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

This molecule is bonded dynamically by mol-witness-patrol's survey-workers step.
Each polecat being monitored gets one arm that runs in parallel with other arms.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| polecat_name | Yes | Name of the polecat to inspect |
| rig | Yes | Rig containing the polecat |

## Step: capture
Capture recent tmux output for toast.

```bash
tmux capture-pane -t gt-gastown-toast -p | tail -50
```

Record:
- Last activity timestamp (when was last tool call?)
- Visible errors or stack traces
- Completion indicators ("Done", "Finished", etc.)

## Step: assess
Categorize polecat state based on captured output.

States:
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **requesting_shutdown**: Sent LIFECYCLE/Shutdown mail
- **done**: Showing completion indicators

Calculate: minutes since last activity.
Needs: capture

## Step: load-history
Read nudge history for toast from patrol state.

```
nudge_count = state.nudges[toast].count
last_nudge_time = state.nudges[toast].timestamp
```

This data was loaded by the parent patrol's load-state step and passed
to the arm via the bonding context.
Needs: assess

## Step: decide
Apply the nudge matrix to determine action for toast.

| State | Idle Time | Nudge Count | Action |
|-------|-----------|-------------|--------|
| working | any | any | none |
| idle | <10min | any | none |
| idle | 10-15min | 0 | nudge-1 (gentle) |
| idle | 15-20min | 1 | nudge-2 (direct) |
| idle | 20+min | 2 | nudge-3 (final) |
| idle | any | 3 | escalate |
| error | any | any | assess-severity |
| requesting_shutdown | any | any | pre-kill-verify |
| done | any | any | pre-kill-verify |

Nudge text:
1. "How's progress? Need any help?"
2. "Please wrap up soon. What's blocking you?"
3. "Final check. Will escalate in 5 min if no response."

Record decision and rationale.
Needs: load-history

## Step: execute
Take the decided action for toast.

**nudge-N**:
```bash
tmux send-keys -t gt-gastown-toast "{{nudge_text}}" Enter
```

**pre-kill-verify**:
```bash
cd polecats/toast
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred
```
If clean: kill session, remove worktree, delete branch
If dirty: record failure, retry next cycle

**escalate**:
```bash
gt mail send mayor/ -s "Escalation: toast stuck" -m "..."
```

**none**: No action needed.

Record: action taken, result, updated nudge count.
Needs: decide

## Output

The arm completes with:
- action_taken: none | nudge-1 | nudge-2 | nudge-3 | killed | escalated
- result: success | failed | pending
- updated_state: New nudge count and timestamp for toast

This data feeds back to the parent patrol's aggregate step.
---
bonded_from: mol-polecat-arm
bonded_to: gt-wewf
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Digest: mol-deacon-patrol

Patrol complete: inbox empty, all agents healthy, cleaned 4 orphans (gt-wx0w, gt-kp3s3, gt-6n1cy, gt-i4lo)


Digest: mol-deacon-patrol

Patrol 12: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol 13: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol 5: Quiet


Merge: gt-72so

branch: polecat/Doof
target: main
source_issue: gt-72so
rig: gastown


Digest: mol-deacon-patrol

Patrol 6


Outpost error handling: Retry logic and resilience

## Overview

Error handling and retry logic for outpost operations.

## Error Types

```go
var (
    ErrOutpostUnreachable = errors.New("outpost unreachable")
    ErrWorkerSpawnFailed  = errors.New("worker spawn failed")
    ErrWorkerTimeout      = errors.New("worker timed out")
    ErrCostCapExceeded    = errors.New("cost cap exceeded")
    ErrAllOutpostsBusy    = errors.New("all outposts at capacity")
)
```

## Retry Policy

```go
type RetryPolicy struct {
    MaxAttempts     int
    InitialBackoff  time.Duration
    MaxBackoff      time.Duration
    BackoffFactor   float64
    RetryableErrors []error
}

func DefaultRetryPolicy() *RetryPolicy {
    return &RetryPolicy{
        MaxAttempts:    3,
        InitialBackoff: 1 * time.Second,
        MaxBackoff:     30 * time.Second,
        BackoffFactor:  2.0,
        RetryableErrors: []error{
            ErrOutpostUnreachable,
            ErrWorkerSpawnFailed,
        },
    }
}
```

## Retry Implementation

```go
func (m *OutpostManager) SpawnWithRetry(issue string, cfg WorkerConfig) (Worker, error) {
    var lastErr error
    backoff := m.retryPolicy.InitialBackoff

    for attempt := 0; attempt < m.retryPolicy.MaxAttempts; attempt++ {
        outpost := m.policy.SelectOutpost(issue, m.outposts)
        if outpost == nil {
            return nil, ErrAllOutpostsBusy
        }

        worker, err := outpost.Spawn(issue, cfg)
        if err == nil {
            return worker, nil
        }

        if !m.isRetryable(err) {
            return nil, err
        }

        lastErr = err
        time.Sleep(backoff)
        backoff = min(backoff * m.retryPolicy.BackoffFactor, m.retryPolicy.MaxBackoff)
    }

    return nil, fmt.Errorf("spawn failed after %d attempts: %w",
        m.retryPolicy.MaxAttempts, lastErr)
}
```

## Outpost Health Tracking

```go
type OutpostHealth struct {
    LastPing      time.Time
    LastError     error
    FailureCount  int
    CircuitBreaker bool  // If true, skip this outpost
}

func (m *OutpostManager) updateHealth(name string, err error) {
    // Track failures, open circuit breaker after N failures
    // Auto-reset after successful ping
}
```

## Config

```yaml
policy:
  retry:
    max_attempts: 3
    initial_backoff: 1s
    max_backoff: 30s

  circuit_breaker:
    failure_threshold: 5
    reset_timeout: 1m
```

## Files

- `internal/outpost/retry.go`
- `internal/outpost/health.go`

## Dependencies

Depends on: gt-9a2.3 (OutpostManager)
Can be done after basic outpost implementations work.


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.


gt spawn: Not injecting work instructions to session

gt spawn starts session but doesn't inject the issue assignment.

Repro:
1. gt spawn gastown/Toast --issue gt-2ux
2. Session starts but polecat just sees Claude prompt
3. No issue context injected

Expected: Polecat should receive issue details automatically.
Actual: Polecat sits at blank prompt, needs manual injection.


Refactor builtin_molecules.go (1620 lines)

## Summary

builtin_molecules.go is 1620 lines and growing. Should be split into:
- builtin_molecules.go - registration and common helpers
- molecules_patrol.go - patrol molecules (deacon, witness, refinery)
- molecules_work.go - work molecules (polecat-work, ready-work, engineer-in-box)
- molecules_session.go - session wrappers (crew-session, polecat-session)

## Benefits
- Easier to find/edit specific molecules
- Smaller diffs on changes
- Clear categorization


mol-deacon-patrol


Test MR

test


Digest: mol-deacon-patrol

Patrol 11: Quiet


Deacon patrol wisps should use town beads, not gastown rig beads

## Problem

The deacon is a town-level role but stores patrol wisps in gastown/mayor/rig/.beads/ (see internal/cmd/prime.go:691). This fails for users who don't have the gastown rig installed.

## Correct Architecture

Deacon -> ~/gt/.beads-wisp/ (town-level, no rig dependency)

Town-level ephemeral work (deacon patrols) should use town wisp storage, just like rig-level ephemeral work (witness/refinery patrols) uses rig wisp storage.

## Implementation Tasks

### 1. Town Setup (gt install / gt town init)

- Create ~/gt/.beads-wisp/ directory during town initialization
- Initialize as git repo (for local commits, not synced)
- Add config.yaml with wisp: true
- Ensure .beads-wisp/ is gitignored at town level

Files:
- internal/cmd/install.go (or equivalent town init)
- internal/town/manager.go (if exists)

### 2. Rig Setup (gt rig init)

Already creates <rig>/.beads-wisp/ - verify this is working:
- internal/rig/manager.go:375 (beadsDir := filepath.Join(rigPath, ".beads-wisp"))
- internal/rig/manager.go:394 (ensureGitignoreEntry)

### 3. Deacon Code Fixes

Update deacon to use town wisp storage:
- internal/cmd/prime.go:691 - change rigBeadsDir to townWispDir
- internal/cmd/sling.go - route deacon wisps to town level
- internal/daemon/daemon.go - any deacon-specific wisp handling

### 4. gt doctor Checks

Add/update doctor checks for wisp directories:
- internal/doctor/wisp_check.go - already checks rig wisps
- Add TownWispCheck to verify ~/gt/.beads-wisp/ exists
- Add TownWispGitCheck to verify it is a valid git repo
- Update existing checks to handle both town and rig levels

Files:
- internal/doctor/wisp_check.go (extend for town level)
- internal/doctor/checks.go (register new checks)

### 5. Documentation

- docs/beads-data-plane.md - already updated with three-tier architecture
- Verify wisp-architecture.md reflects town-level wisps

## Testing

1. Fresh gt install should create ~/gt/.beads-wisp/
2. gt doctor should pass with no rig installed
3. Deacon patrol should work without gastown rig
4. gt sling patrol deacon/ --wisp should route to town wisps


Update gt doctor to check new config locations

Doctor should validate new structure:
- Check mayor/config.json exists and is valid
- Check settings/ exists for each rig
- Warn if old .gastown/ files still exist
- Offer --fix to migrate old locations to new


Merge: gt-rp0k

branch: polecat/nux
target: main
source_issue: gt-rp0k
rig: gastown


Digest: mol-deacon-patrol

Patrol 13: Quiet


Add deacon/ mail identity support

Ensure deacon/ works as a mail identity in town-level beads. Test with bd mail send deacon/ and bd mail inbox --identity deacon/.


Test Polecat Arm

Test child for bonding pattern


Generate handoff summary

Summarize this patrol cycle for digest.

Include:
- Workers inspected (count, names)
- Nudges sent (count, to whom)
- Sessions killed (count, names)
- Escalations (count, issues)
- Issues found (brief descriptions)
- Actions pending for next cycle

This becomes the digest when the patrol wisp is squashed.


Digest: mol-deacon-patrol

Patrol 7: routine


Work request: gt-976 crew lifecycle support

Hey Max, filed gt-976 for you - adding crew lifecycle support to Deacon.

Currently crew is 'human-managed' and can't request automated refresh. Would be useful for molecules that need fresh sessions mid-workflow.

Key changes:
- getManager(RoleCrew) → return deacon/ instead of human
- Teach Deacon crew session patterns
- Test with gt nudge

Priority 2, no rush but would unblock molecule automation for crew.

- Dave (beads/crew/dave)


Digest: mol-deacon-patrol @ 2025-12-24 19:27

Patrol 14


Digest: mol-deacon-patrol

Patrol #14


Missing standard OSS files: CONTRIBUTING, CODE_OF_CONDUCT, SECURITY

For OSS launch, we need:
1. CONTRIBUTING.md - How to contribute, PR process, code style
2. CODE_OF_CONDUCT.md - Community standards
3. SECURITY.md - How to report vulnerabilities

These are expected by OSS communities and GitHub surfaces them in repo UI.


Digest: mol-deacon-patrol

Patrol 5: all clear, proto closure warning noted


Design molecule parameterization

Enable protos to accept parameters for customization.

## Use Cases

1. rig-spinup needs rig name: `gt sling rig-spinup --param rig=newproject`
2. agent-restart needs agent: `gt sling agent-restart --param agent=gastown/witness`
3. code-review needs scope: `gt sling code-review --param scope=src/auth/`

## Proposed Syntax

### In Proto

```markdown
## Step: create-rig-structure
mkdir -p ~/gt/${rig}/refinery ~/gt/${rig}/witness
```

### In Sling

```bash
gt sling rig-spinup mayor/ --param rig=newproject --wisp
```

### In Bonded Molecule

Interpolation happens at bond time. Step descriptions have concrete values.

## Implementation

1. Proto declares params in frontmatter: `params: [rig]`
2. gt sling validates required params provided
3. bd mol bond receives params, interpolates descriptions
4. Bonded molecule has concrete step text

## Edge Cases

- Missing required param → error
- Unused param → warning
- Param in step title → interpolate there too


Digest: mol-deacon-patrol

Patrol 18: All clear


Digest: mol-deacon-patrol

Patrol 13: All clear


Check own context usage.

Check own context usage.

If context is HIGH (>80%):
- Write handoff summary
- Prepare for burn/respawn

If context is LOW:
- Can continue processing

instantiated_from: mol-refinery-patrol
step: context-check


Daemon: Implement exponential backoff based on activity file

Modify daemon heartbeat logic to use exponential backoff when idle.

Read ~/gt/daemon/activity.json on each heartbeat.
Compute idle duration: time.Since(activity.Timestamp)
Adjust next ticker interval based on idle duration:

| Idle Duration | Next Heartbeat |
|---------------|----------------|
| 0-5 min       | 5 min (base)   |
| 5-15 min      | 10 min         |
| 15-45 min     | 30 min         |
| 45+ min       | 60 min (max)   |

Implementation:
1. Add activity file reading to daemon heartbeat
2. Replace fixed ticker with dynamic interval calculation
3. Reset to base interval when activity is fresh

No counter tracking needed - pure discovery from single timestamp.

CROSS-RIG DEPENDENCY: Also requires beads:bd-v8ku (assigned to beads/crew/dave)


Digest: mol-deacon-patrol

Patrol 14: all healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously,
handling callbacks, monitoring rig health, and performing cleanup.
Each patrol cycle runs these steps in sequence, then loops or exits.


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 8: OK


MQ conflict prediction: file hotspot tracking

Track which files change frequently to predict conflicts before spawn.

## Goal
Before spawning a polecat on an issue, warn if the target files are "hot" (recently changed by other MRs).

## Approach
1. Track file change frequency per MR (sliding window, e.g., last 24h)
2. At spawn time, analyze issue description / planned changes
3. If touching hot files, either:
   - Warn and proceed
   - Suggest waiting for queue to clear
   - Auto-assign to ownership zone (future)

## Implementation
- Add file_changes log to refinery state (or separate hotspot.json)
- After each merge, record changed files with timestamp
- gt spawn checks hotspots before assignment
- Optional: Witness patrol aggregates hotspot data

## Example
```
$ gt spawn --issue gt-xyz
Warning: This issue likely touches auth/login.go
  - Changed 3 times in last 2 hours
  - 2 MRs pending that also touch this file
Proceed anyway? [y/N]
```

## Parent
gt-lxxh2


Digest: mol-deacon-patrol

Patrol 18: routine


Digest: mol-deacon-patrol

Patrol cycle 8: all nominal


Add migration path for existing rigs

Existing rigs have refinery as clone. Need migration path.

## Options
1. Manual: User runs 'gt rig migrate' or similar
2. Automatic: Detect clone, convert to worktree on next start
3. Deprecation: Old rigs work but warn, new rigs use worktree

## Considerations
- Don't break existing setups
- Clear upgrade path
- Handle in-flight MRs during migration


Execute registered plugins

Execute registered plugins.

Scan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with
YAML frontmatter defining its gate (when to run) and instructions (what to do).

See docs/deacon-plugins.md for full documentation.

Gate types:
- cooldown: Time since last run (e.g., 24h)
- cron: Schedule-based (e.g., "0 9 * * *")
- condition: Metric threshold (e.g., wisp count > 50)
- event: Trigger-based (e.g., startup, heartbeat)

For each plugin:
1. Read plugin.md frontmatter to check gate
2. Compare against state.json (last run, etc.)
3. If gate is open, execute the plugin

Plugins marked parallel: true can run concurrently using Task tool subagents.
Sequential plugins run one at a time in directory order.

Skip this step if ~/gt/plugins/ does not exist or is empty.


loop-or-exit

Decision: burn and loop if context low, exit for respawn if context high.


Guardrail: Verify commits exist before closing polecat issues

## Updated Approach (ZFC)

The original proposal was for mechanical guardrails in bd close. This contradicts the ZFC principle: all decisions go to models, not code.

## Correct Solution

The verification should happen in **mol-polecat-arm** execute step, not bd close:

In the pre-kill-verify action:
```bash
# Current steps
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred

# ADD: Verify productive work
git log --oneline --grep='<issue-id>' | head -1
# If no commits AND issue being closed as 'done' → flag for review
```

The agent (Witness) makes the decision. The mol gives it the verification step.

## Why Not Code Guardrails

Polecats have legitimate reasons to close issues without commits:
- Already done (someone else fixed it)
- Deferred (out of scope)
- Escalated (needs human decision)
- Duplicate (merged with another issue)

A code guardrail would block all these. The mol step lets the agent verify AND make the judgment call.

## Implementation

Update mol-polecat-arm execute step to include commit verification for 'done' closures.


Agent parking and resuming

Implement gt park and gt resume commands. Agent parks work on a gate, state persists across sessions. When gate condition met, Deacon sends wake mail. Agent resumes from parked state. Critical for async workflows.


Digest: mol-deacon-patrol

Patrol 15: All healthy


Find abandoned work

Find abandoned work.

Scan for orphaned state:
- Issues marked in_progress with no active polecat
- Polecats that stopped responding mid-work
- Merge queue entries with no polecat owner
- Wisp sessions that outlived their spawner

```bash
bd list --status=in_progress
gt polecats --all --orphan
```

For each orphan:
- Check if polecat session still exists
- If not, mark issue for reassignment or retry
- File incident beads if data loss occurred


Digest: mol-deacon-patrol

Patrol 8: All clear


Digest: mol-deacon-patrol

Patrol #1: All agents healthy, no messages, no orphans