mol-theme-generate: Custom name pool generation via cognition

Currently polecat name themes are hardcoded in namepool.go. Simple theme selection is fine as static config, but custom name generation should be a molecule.

Examples requiring cognition:
- "Generate 50 polecat names in the style of [book/movie/game]"
- "Create names that match the project's domain (medical, financial, etc.)"
- "Extend the mad-max theme with 20 more obscure characters"

## Molecule: theme-generate
Generate custom polecat names for a rig.

## Step: analyze-request
Understand the naming request:
- Theme style or source material
- Number of names needed
- Any constraints (length, format)

## Step: generate-candidates
Generate candidate names matching the style.
Aim for 2x the requested count.

## Step: validate-names
Filter candidates:
- No duplicates with existing themes
- Appropriate length (3-15 chars)
- No problematic terms

## Step: create-theme
Write the custom theme to rig config or beads.
Register in name pool.
Needs: validate-names

## Notes
- Output is a new theme entry in BuiltinThemes equivalent
- Could be stored as a pinned bead for persistence


Digest: mol-deacon-patrol

Cycle 4: quiet patrol


Merge: beads-2nh

branch: fix/spawn-beads-path
target: main
source_issue: beads-2nh
rig: gastown


Digest: mol-deacon-patrol

P17: stable


Design: Collapse mail into beads

## Proposal

Replace the separate mail system (JSONL inboxes) with beads issues using a naming convention.

## Rationale

If all state should be in beads (work items, swarm state, dependencies), why have a separate system for messages? Mail is just:
- Handoffs (agent → self)
- Commands (Mayor → Refinery)
- Escalations (Witness → Mayor)

These can all be beads issues with a special prefix.

## Design

### Convention
- Messages use `@-` prefix: `@-witness-1734012345`
- Assignee = recipient
- Status: open = unread, closed = read/acknowledged
- Priority 0 = urgent

### Commands (thin wrappers)
```bash
gt mail send witness -s "Subject" -m "Body"
  → bd create --prefix=@ --title="Subject" --assignee=witness --description="Body"

gt mail inbox
  → bd list --prefix=@ --assignee=$(gt whoami) --status=open

gt mail read @-abc
  → bd show @-abc && bd close @-abc
```

### Notification
Daemon watches for new `@-` issues and pokes relevant sessions.
Or: agents poll on heartbeat (simpler).

## What We Remove
- `mail/inbox.jsonl` files
- Mail JSONL read/write code
- Separate delivery mechanism

## What We Keep
- `gt mail` CLI (as wrapper)
- Handoff semantics
- Notification (via daemon or polling)

## Benefits
- One system, one sync, one query interface
- All communication in git history
- Simpler architecture

## Risks
- Beads prefix filtering must be efficient
- Namespace collision with user prefixes
- Performance for high-frequency messages (probably fine for handoffs)

## Decision Point
Do we need first-class mail support in beads (`bd mail` commands) or is convention sufficient?


Digest: mol-deacon-patrol

Patrol 10: Routine


Digest: mol-deacon-patrol

Patrol 2: routine, all healthy


Merge: gt-xw7b

branch: polecat/morsov
target: main
source_issue: gt-xw7b
rig: gastown


Digest: mol-deacon-patrol

Patrol 9: healthy


gt channel publish command

New CLI command for ephemeral broadcast to channels.

## Deliverables

1. New command: gt channel publish <channel> <message>
   - Example: gt channel publish #witnesses "Swarm incoming"
2. Resolve channel to running sessions
3. Nudge each session with message
4. Report delivery status

## Usage
```bash
gt channel publish #town "Handoff in 5 minutes"
gt channel publish #rig/gastown "Merge queue paused"
```

## Dependencies
- #channel resolution (gt-???)

## Acceptance
- Command works with #channel syntax
- Message delivered to running sessions
- Clear output showing delivery status


Digest: mol-deacon-patrol

Patrol 5: All green


Merge: gt-h6eq.1

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


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 18: All clear


Unify tmux session lifecycle: prefer exec-over-shell pattern

## Context

When `gt crew at` is run from INSIDE the target session, it uses `execClaude()` which
replaces the shell with Claude directly. This is actually preferable behavior:
- Cleaner exit (no intermediate shell prompt)
- More reliable for programmatic worker recycling
- Better UX for humans

But currently this only happens accidentally when you run `gt crew at` while already
in the session at a shell prompt.

## Current behavior

1. Session created: `tmux new-session` starts with shell
2. Claude started via `send-keys` → shell spawns claude as child
3. Exit claude → return to shell → exit shell → session ends

With exec path (only if already in session):
1. `execClaude()` replaces shell with claude
2. Exit claude → session ends (no intermediate shell)

## Desired behavior

Consider making exec-the-shell the DEFAULT for all crew/persistent sessions:
- Spawn session with shell
- Wait for ready
- Use `respawn-pane -k` with claude command (kills shell, starts claude directly)

This gives the cleaner lifecycle without requiring the user to be inside the session.

## Related

Part of tmux control plane unification - ability to manage workers from any session.


Add gt hook command (wrapper for bd hook)

Add a thin wrapper command `gt hook` that calls `bd hook` to inspect what's pinned to an agent's hook.

## Usage

```bash
gt hook                    # Show what's on current agent's hook
gt hook --agent deacon     # Show Deacon's hook
gt hook --agent gastown/furiosa  # Show polecat's hook
```

## Implementation

Thin wrapper in gt that:
1. Determines current agent identity
2. Calls `bd hook [--agent <name>]`
3. Formats output for gt context

## Why gt wrapper?

- Consistent with gt ecosystem (gt mail, gt status, etc.)
- Can add gt-specific context (session status, etc.)
- Easier discovery for gt users

## Related

- bd hook command (implemented by Dave)
- Chemistry UX design: gastown/mayor/rig/docs/chemistry-design-changes.md


Merge: gt-5af.5

branch: polecat/Scabrous
target: main
source_issue: gt-5af.5
rig: gastown


Digest: mol-deacon-patrol

Patrol 10: Nominal - halfway point


Review: Refinery patrol template changes (gt-qz2l)

Polecat dementus implemented refinery template changes: banners, wisp-based execution, propulsion protocol. Review for correctness and consistency with witness/deacon patterns.


Digest: mol-deacon-patrol

Patrol 11: All healthy, dave now running


Add 'gt account default' command

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


Digest: mol-deacon-patrol

Patrol 5: All healthy


Digest: mol-deacon-patrol

Patrol 15: Routine


Add molecules.jsonl as separate catalog file for template molecules


Digest: mol-deacon-patrol

Patrol 6


Digest: mol-deacon-patrol

Patrol 3: all quiet


Merge: gt-3x1.3

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


Digest: mol-deacon-patrol

Patrol complete: no work, gastown refinery came online, town healthy


decide-actions

Apply nudge matrix and queue actions.

Progressive nudge levels:
- Level 1: Gentle reminder
- Level 2: Stronger nudge
- Level 3: Final warning
- Level 4: Escalate to Mayor

Needs: inspect-workers


Digest: mol-deacon-patrol

Patrol 4: Quick cycle, all quiet


Agent state lifecycle incomplete for polecats

## Problem

The witness patrol formula (mol-witness-patrol.formula.toml) expects polecats to self-report states:
- running
- idle
- stuck
- done

But looking at the code, the only state transitions that actually happen are:

1. **spawning** - Set when polecat is created (polecat/manager.go:170)
2. **running** - Set when agent runs `gt prime` (prime.go:112)
3. **dead** - Set by daemon when agent goes unresponsive (daemon/lifecycle.go:647)

**Missing transitions:**
- `stuck` - No code path exists for agents to report this
- `done` - No code path exists for agents to report this
- `idle` - Only set for infrastructure agents, never for polecats

## Impact

The witness cannot rely on agent_state to detect stuck or done polecats, contradicting the ZFC principle stated in the formula.

## Found in commit

f3a6ef6 (feat: Witness reads polecat state from agent beads)

## Suggested fix

Add code paths for polecats to self-report:
1. `gt done` should update agent_state to "done"
2. When stuck (detected how?), agent should update to "stuck"
3. Consider if "idle" makes sense for polecats (no current work)


Digest: mol-deacon-patrol

Patrol 8: All clear


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.


Replace WaitForClaudeReady with gt peek for steady-state agent observation

## Problem

WaitForClaudeReady uses regex to detect Claude's prompt, which is a ZFC violation.

## Architectural Fix

**Bootstrap (ZFC violation acceptable):**
During cold town startup, no AI is available. Regex to get Deacon online is acceptable.

**Steady State (proper ZFC):**
Once any agent is running, AI should observe AI:
- Deacon starting polecats → Deacon uses gt peek
- Deacon restarting → Mayor watches via gt peek
- Mayor restarting → Deacon watches via gt peek

## Implementation

1. Keep WaitForClaudeReady for daemon bootstrap only
2. Update gt deacon trigger-pending to use gt peek
3. Document bootstrap vs steady-state distinction


Update prompts.md: Engineer role and templates

Update docs/prompts.md with Engineer role:

1. Role Prompts table: Change Refinery to Engineer
2. Add Engineer-specific prompts:
   - Session restart request template
   - Subtask filing template
   - Handoff mail template
3. Update refinery.md template name to engineer.md
4. Ensure consistency with architecture.md


Document Overseer role (human operator)

Document the Overseer role in Gas Town architecture.

## The Overseer

The **Overseer** is the human operator of Gas Town. Not an agent - a person.

## Responsibilities

| Area | Overseer Does | Mayor/Agents Do |
|------|---------------|-----------------|
| Strategy | Define project goals | Execute toward goals |
| Priorities | Set priority order | Work in priority order |
| Escalations | Final decision on stuck work | Escalate to Overseer |
| Resources | Provision machines | Use allocated resources |
| Quality | Review & approve swarm output | Produce output |
| Operations | Run gt commands, monitor dashboards | Do the work |

## Key Interactions

### Overseer → Mayor
- Start/stop Mayor sessions
- Direct Mayor via conversation
- Review Mayor recommendations
- Approve cross-rig decisions

### Mayor → Overseer (Escalations)
- Stuck workers after retries
- Resource decisions (add machines, polecats)
- Ambiguous requirements
- Architecture decisions

## Operating Cadence

Typical Overseer workflow:
1. Morning: Check status, review overnight work
2. During day: Monitor, respond to escalations, adjust priorities
3. End of day: Review progress, plan next batch

## Commands for Overseers

```bash
gt status              # Quick health check
gt doctor              # Detailed diagnostics
gt doctor --fix        # Auto-repair issues
gt inbox               # Messages from agents
gt stop --all          # Emergency halt
```

## Documentation Updates

Add to docs/architecture.md:
- Overseer section under Agent Roles
- Clarify Mayor reports to Overseer
- Add Overseer to workflow diagrams


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.


Polecat CLAUDE.md: configure auto-approve for bd and gt commands

Polecats get stuck waiting for bash command approval when running
bd and gt commands. Need to configure Claude Code to auto-approve these.

Options:
1. Add allowedTools to polecat CLAUDE.md
2. Configure .claude/settings.json in polecat directory
3. Use --dangerously-skip-permissions flag (not recommended)

Should auto-approve:
- bd (beads commands)
- gt (gastown commands)
- go build/test
- git status/add/commit/push

Should still require approval:
- rm -rf
- Arbitrary commands outside project

Related to polecat prompting (gt-e1y, gt-sd6).


Refinery-Witness communication protocol

Define mail protocol between Refinery and Witness:

FROM Witness → Refinery:
- 'Polecat ready': polecat X completed work, ready for merge
- 'Rework complete': polecat Y finished requested rework

FROM Refinery → Witness:
- 'Merge success': polecat X merged, can be cleaned up
- 'Merge failed': polecat X needs rework on <reason>
- 'Rework request': please have a polecat rebase X on current main

Implement as structured mail with parseable format.


submit-merge

Submit to merge queue. Create branch if needed.
Verify CI passes.

gt done  # Signal work ready for merge queue

If there are CI failures, fix them before proceeding.

Depends: rebase-main


Add gt rig rename command

Allow renaming a rig after creation. Similar to gt crew rename, this should:

- Update the directory name
- Update mayor/rigs.json entry
- Update the rig's config.json
- Handle running agents gracefully (require shutdown first or --force)

Use case: User creates a rig, later wants to change its name for better organization.


Nudge newly spawned polecats

Nudge newly spawned polecats that are ready for input.

When polecats are spawned, their Claude session takes 10-20 seconds to initialize.
The spawn command returns immediately without waiting. This step finds spawned
polecats that are now ready and sends them a trigger to start working.

```bash
# For each rig with polecats
for rig in gastown beads; do
    gt polecats $rig
    # For each working polecat, check if Claude is ready
    # Use tmux capture-pane to look for "> " prompt
done
```

For each ready polecat that hasn't been triggered yet:
1. Send "Begin." to trigger UserPromptSubmit hook
2. The hook injects mail, polecat sees its assignment
3. Mark polecat as triggered in state

Use WaitForClaudeReady from tmux package (polls for "> " prompt).
Timeout: 60 seconds per polecat. If not ready, try again next cycle.


Add unit tests for internal/mrqueue package

attached_args: mrqueue package tests

Add comprehensive tests for the merge request queue package.

## Files to create
- internal/mrqueue/mrqueue_test.go

## Test cases to cover
1. NewQueue creates queue directory
2. Add() persists MR to queue
3. Get() retrieves MR by ID
4. List() returns all MRs
5. Remove() deletes MR
6. MR serialization/deserialization
7. Queue handles concurrent access

## Acceptance criteria
- [ ] internal/mrqueue/mrqueue_test.go created
- [ ] At least 6 test functions
- [ ] Tests pass: go test ./internal/mrqueue/...
- [ ] Coverage > 70%


Dogs: Deacon's Helper Workers

## Overview

Dogs are reusable workers managed by the Deacon for infrastructure and cleanup tasks.
They parallel how Polecats serve the Witness, but at town level with cross-rig scope.

## Key Concepts

- **Dogs**: Deacon-managed, reusable, infrastructure/cleanup tasks
- **Kennel**: Where dogs live (`deacon/dogs/`)
- **Multi-rig worktrees**: Dogs have worktrees into multiple rigs for cross-rig work

## Cats vs Dogs

| Aspect | Polecats | Dogs |
|--------|----------|------|
| Manager | Witness | Deacon |
| Scope | Per-rig | Town (cross-rig) |
| Lifecycle | Ephemeral | Reusable |
| Work | Features | Infrastructure |
| Location | `<rig>/polecats/` | `deacon/dogs/` |

## Implementation

### Phase 1: Dog Infrastructure
- `gt dog add/remove/list/call/status` commands
- Kennel directory structure (`~/gt/deacon/dogs/`)
- Multi-rig worktree creation
- Dog state tracking

### Phase 2: Deacon Dispatch
- Sling support for `deacon/dogs` target
- Pool management (spawn/retire logic)
- Completion mail handling

### Phase 3: Infrastructure Formulas
- mol-convoy-cleanup
- mol-dep-propagate
- mol-digest-generate

### Phase 4: Deacon Refactor
- Patrol becomes detect → dispatch
- Heavy work moves to dog slings

## Reference

- docs/patrol-system-design.md#dogs-deacons-helper-workers
- docs/PRIMING.md (Role Taxonomy)


gt dog add/remove/list/call/status CLI

Dog management commands:
- gt dog add <name> - Create dog in kennel with multi-rig worktrees
- gt dog remove <name> - Retire dog, cleanup worktrees
- gt dog list - Show the pack (all dogs with status)
- gt dog call [name] - Wake idle dog(s)
- gt dog status [name] - Show detailed dog state


Kennel directory structure and multi-rig worktrees

Create kennel infrastructure:
- ~/gt/deacon/dogs/<name>/ directory
- Worktrees into each rig (gastown, beads, etc.)
- .dog.json state file (idle/working, last-active, assigned-work)
- Worktree refresh/cleanup logic


gt sling support for deacon/dogs target

Extend gt sling to support dog targets:
- gt sling <work> deacon/dogs - Auto-dispatch to idle dog
- gt sling <work> deacon/dogs/alpha - Specific dog
- Dog pool management (spawn if needed, up to max)
- Completion mail handling


Deacon patrol refactor: detect → dispatch

Refactor Deacon patrol to delegate heavy work to dogs:
- check-conditions → sling to dog (not inline execution)
- Pool maintenance step (spawn/retire/refresh)
- Completion mail handling from dogs
- Keep patrol lightweight (detection only)


Infrastructure formulas for dog tasks

Create formulas for dog-executed tasks:
- mol-convoy-cleanup: Archive convoy, notify overseer
- mol-dep-propagate: Cross-rig dependency resolution
- mol-digest-generate: Daily digest for overseer
- mol-orphan-scan: Find and reassign orphaned work
- mol-session-gc: Clean stale sessions


Digest: mol-deacon-patrol

Patrol 7: all healthy


Digest: mol-deacon-patrol

P10: stable


test pin fix 2


Messaging infrastructure: lists, queues, and channels

## Problem

Current messaging is point-to-point only:
- Mail: A → B (durable, polling)
- Nudge: A → B (ephemeral, real-time)

No support for broadcast, work queues, or pub/sub patterns.

## Design

### Addressing Syntax

| Prefix | System | Resolution | Storage | Claim? |
|--------|--------|------------|---------|--------|
| `agent/` | Mail | Direct | Recipient inbox | N/A |
| `@group` | Mail | Dynamic (filesystem) | Fan-out (N copies) | No |
| `list:name` | Mail | Static config | Fan-out (N copies) | No |
| `queue:name` | Mail | Static config | Shared (1 copy) | Yes |
| `announce:name` | Mail | Static config | Shared (1 copy) | No |
| `#channel` | Nudge | Dynamic (tmux) | None (ephemeral) | No |

### Dynamic Aliases

- `@rig/gastown` → scan ~/gt/gastown/ for agent dirs (witness, refinery, crew/*, polecats/*)
- `@town` → scan ~/gt/ for all agent dirs
- `@witnesses` → for each rig, include <rig>/witness
- `@crew/gastown` → scan ~/gt/gastown/crew/*
- `#rig/gastown` → scan tmux for gastown/* sessions
- `#town` → scan tmux for all Gas Town sessions

**Mail** resolves against filesystem (agents that exist)
**Channels** resolve against tmux (agents that are running)

### Static Config

Location: `~/gt/config/` (JSON format, machine-edited)

```json
// lists.json
{
  "oncall": ["mayor/", "gastown/witness", "beads/witness"],
  "cleanup/gastown": ["gastown/witness", "deacon/"]
}
```

### Work Queue Semantics

- `gt mail send queue:cleanup/gastown -s "Task" -m "..."`
- `bd update <msg-id> --claim` → atomic claim (sets assignee + in_progress)
- If already claimed, returns error "already claimed by X"

### Use Cases

1. **Polecat spawn**: `gt mail send @rig/gastown` → Witness + Deacon both notified
2. **Polecat cleanup**: `gt mail send queue:cleanup/gastown` → first to claim handles it
3. **Town broadcast**: `gt mail send @town -s "Handoff now"` → everyone gets copy
4. **Real-time alert**: `gt channel publish #witnesses "Swarm incoming"`

## Implementation Tasks

1. Create ~/gt/config/ directory structure
2. Implement dynamic alias resolution (filesystem scan)
3. Implement static list lookup (config/lists.json)
4. Add fan-out at send time for @/list: addresses
5. Implement queue: with shared storage
6. Add `bd update --claim` for work queue semantics
7. Implement channel resolution (tmux scan)
8. Add `gt channel publish` command


Standardize error handling and warning output patterns

Inconsistent patterns across codebase:

Error wrapping:
- Some: fmt.Errorf("context: %w", err) (good)
- Some: return err (loses context)
- Some: fmt.Errorf("message", rigName) without wrapping original

Exit handling in Cobra commands:
- Some use os.Exit(1) inside RunE (bad - loses error chain)
- Some properly return errors

Warning output styles:
- fmt.Printf("%s Warning: ...", style.Dim.Render("⚠"))
- fmt.Printf("Warning: %s", ...)
- fmt.Fprintf(os.Stderr, "warning: ...")

Suggestion:
1. Always wrap errors with %w
2. Never call os.Exit() in RunE handlers
3. Standardize on style.Warning.Render("Warning:") pattern


Day 4.5: Test multi-step molecule lifecycle

Integration test (UPDATED for self-managed handoffs):
1. Sling work with molecule to polecat
2. Polecat works through all steps (self-handoffs as context fills)
3. Polecat calls gt done when work complete
4. Witness verifies clean state and sends MERGE_READY to refinery
5. Refinery merges branch
6. Refinery sends MERGED to witness
7. Witness calls gt polecat nuke for full cleanup
8. Verify clean state (no worktree, no branch, agent bead closed)

**VALIDATED**: rictus lifecycle worked end-to-end: gt done → witness → refinery → merged

Parent: gt-4a2qt


Digest: mol-deacon-patrol

Patrol 1: All healthy, no lifecycle requests, no orphans


Digest: mol-deacon-patrol

Cycle 3: quiet patrol


Work on ga-xxp: Define mol-polecat-work standard molecule...

Work on ga-xxp: Define mol-polecat-work standard molecule. See bd show ga-xxp for full details.


Digest: mol-deacon-patrol

Patrol 18: Green


Digest: mol-deacon-patrol

Patrol 15: routine


Digest: mol-deacon-patrol

P5: stable


implement

Implement the solution for gt-test. 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.

Depends: load-context


Doctor check: Zombie session cleanup

Detect and clean up zombie tmux sessions via gt doctor.

## Problem

Zombie sessions occur when:
- Agent crashes without cleanup
- gt kill fails mid-operation
- System restart leaves orphan sessions
- Session naming collision

## Checks

### ZombieSessionCheck
- List all tmux sessions matching gt-* pattern
- Cross-reference with known polecats
- Flag sessions with no corresponding polecat state
- Flag sessions for removed polecats
- Check session age vs polecat creation time

### Detection Criteria
- Session exists but polecat directory doesn't
- Session name doesn't match any registered polecat
- Polecat state=idle but session running
- Multiple sessions for same polecat

## Output

```
[WARN] Zombie tmux sessions detected:
  - gt-wyvern-OldPolecat (polecat removed)
  - gt-beads-Unknown (no matching polecat)
  - gt-wyvern-Toast (duplicate session)

  Run 'gt doctor --fix' to clean up
```

## Auto-Fix (--fix flag)

- Kill orphan tmux sessions
- Update polecat state to match reality
- Log all cleanup actions

## Safety

- Never kill sessions where polecat state=working
- Prompt before killing if --fix used without --force
- Create audit log of killed sessions


gt refinery start: doesn't actually start a session

## Problem

`gt refinery start gastown` reports success but doesn't start a tmux session.

## Evidence

```
$ gt refinery start gastown
Starting refinery for gastown...
✓ Refinery started for gastown

$ tmux list-sessions | grep refinery
(nothing)

$ gt refinery status gastown
State: ○ stopped
```

## Expected

Should start a tmux session (e.g., gt-gastown-refinery) with Claude processing the merge queue.

## Related

- gt-kcee: Witness commands also need implementation
- The refinery 'start' may just be updating state.json without spawning a session


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

Patrol 14


Digest: mol-deacon-patrol

Patrol 7: All agents healthy


Digest: mol-deacon-patrol

Patrol: mayor handoff (Batch 1 complete, notifications working), 5 polecats now active (Batch 2)


Digest: mol-deacon-patrol

Patrol 12: Quiet


Merge: gt-qsvq

branch: polecat/capable
target: main
source_issue: gt-qsvq
rig: gastown


gt sling fails for terminated polecats even with --naked flag

## Problem
When a polecat terminates after completing work (submits MR, session ends), the polecat directory still exists but the tmux session is gone. Attempting to sling new work to that polecat fails:

```
gt sling bd-fa1q beads/Toast --naked
Error: resolving target: getting pane for gt-beads-toast: exit status 1
```

The `--naked` flag should bypass tmux pane requirements, but the error occurs during target resolution before the flag is checked.

## Expected Behavior
`gt sling <bead> <polecat> --naked` should:
1. Attach work to the polecat hook
2. Skip session creation (manual start later)
3. NOT require an existing tmux pane

## Workaround
Use crew workers instead (they have persistent sessions).

## Fix
Target resolution should check `--naked` flag before attempting pane lookup, or provide a way to respawn terminated polecats.

Fixed: resolveTargetAgent now skips tmux pane lookup when --naked flag is set


Merge: gt-svi.1

type: merge-request
branch: polecat/Max
target: main
source_issue: gt-svi.1
rig: gastown


Polecat auto-start: Claude doesn't process initial nudge

After gt sling spawns a polecat, the 'Work slung' message is sent to tmux but Claude sits idle at the prompt. The SessionStart hook doesn't fire because no user input was received.

Observed:
- gt sling successfully spawns polecat, creates worktree, starts Claude
- Sends 'Work slung: gt-xxx. Start working on it now...' to the pane
- Claude shows idle prompt 'Try refactor...' and doesn't process the message

Expected:
- Polecat should auto-start working on the slung issue

Root cause hypothesis:
- The nudge is sent as tmux send-keys which goes to the input line
- Claude needs Enter to be pressed to submit the prompt
- SessionStart hook only fires after first user message

Workaround:
- Send extra Enter after the nudge message
- Or use daemon's triggerPendingSpawns to send Enter after Claude is ready


Digest: mol-deacon-patrol

Patrol 3: routine, all healthy


Digest: mol-deacon-patrol

P6: stable, beads polecats exited


Digest: mol-deacon-patrol

Patrol 3: All healthy


Code review: handoff.go changes (gt-yt6g, gt-tocb)

Review ~80 lines of Go changes to internal/cmd/handoff.go:

## Commits to review
- 1414081: Standardize session end with gt handoff (gt-yt6g)
  - Detect polecats via GT_POLECAT env var
  - Call gt done instead of respawning for polecats
  - +31/-11 lines

- 9c85b83: Support full session paths in gt handoff (gt-tocb)
  - resolveRoleToSession accepts <rig>/crew/<name>, <rig>/witness, <rig>/refinery
  - +46/-3 lines

## Review focus
- Error handling in path resolution
- Edge cases in polecat detection
- Test coverage needed?


Test message

Test body


Digest: mol-deacon-patrol

Patrol 8: OK


Digest: mol-deacon-patrol

Patrol cycle 6: routine, healthy


gt crew restart command

Add a 'gt crew restart' command that kills the tmux session and restarts fresh. Useful when a crew member gets confused or needs a clean slate.

Should:
- Kill existing tmux session if running
- Start fresh session with claude
- Run gt prime to reinitialize context

Alias: gt crew rs


Digest: mol-deacon-patrol

Patrol 2 complete: all healthy, no issues


Digest: mol-deacon-patrol

Patrol #5: Routine - 6 sessions healthy


gt mail read: Support numeric indices for message ID

Allow 'gt mail read 1' to read the first message in inbox.

Current behavior requires full message ID like 'msg-abc123'.
Should support:
- Numeric index: 'gt mail read 1' reads first/newest message
- Partial ID match: 'gt mail read abc' matches 'msg-abc123'

This is a UX improvement - agents frequently type 'gt mail read 1'.


Digest: mol-deacon-patrol

Patrol 1: All healthy - Mayor OK, 2 witnesses, 2 refineries, 0 polecats, 8 sessions, no callbacks


Digest: mol-deacon-patrol

Cycle 8: quiet


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-1iwk
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


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


Add tests for gt crew restart --all

Add integration tests for the crew restart flow:

- Test getAgentSessions() correctly identifies crew sessions
- Test --rig filtering works correctly
- Test --dry-run outputs correct targets
- Test session kill/recreate cycle (without Claude)

Consider extracting a SessionStarter interface to mock the claude-launching bit.

Related: gt crew restart --all was just implemented.


mol-deacon-patrol

Deacon patrol molecule template. Label: template


CLI: workspace commands (init, add, list)

GGT needs workspace management commands beyond install.

## Commands (beyond gt-f9x.3 install)

### gt workspace list
List all rigs in current workspace.
```
gt workspace list [--json]
```
Essentially `gt rig list` but framed as workspace view.

### gt workspace add
Add existing rig to workspace (alternative to gt rig add).
```
gt workspace add <git-url> [--name NAME]
```

### gt onboard
Interactive first-time setup wizard.
```
gt onboard
```
- Prompts for workspace location
- Creates structure via gt install
- Offers to add first rig

## Note
May be redundant with gt-f9x.3 (install) and gt-u1j.16 (rig commands).
Consider if this is needed or should be closed as covered by those.

## PGT Reference
gastown-py/src/gastown/cli/workspace_cmd.py


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

Patrol 16: All healthy


town handoff command (optional)

CLI commands for session handoff workflow (optional convenience).

## Commands

### gt handoff
Generate handoff interactively.
```
gt handoff [--send]
```
- Collects current state (status, inbox, beads)
- Prompts for additional notes
- --send: Mail to self and exit

### gt resume
Check for and display pending handoff.
```
gt resume
```
- Checks inbox for handoff message
- Displays formatted handoff if found
- Suggests next actions

## Implementation

These are convenience wrappers. The same workflow can be done manually:
```bash
# Manual handoff
town status > /tmp/handoff
town inbox >> /tmp/handoff
bd ready >> /tmp/handoff
# Edit and send
town mail send mayor/ -s "Session Handoff" -f /tmp/handoff
```

## Priority

P2 - Optional. Manual workflow works fine. Nice to have for UX.

## Notes

Part of session cycling workflow designed in [deleted:gt-u82].


Digest: mol-deacon-patrol

Patrol cycle 15: All healthy


Add unit tests for internal/mail router and mailbox

attached_args: Add unit tests for mail router and mailbox

Add tests for mail routing and mailbox functionality.

## Files to create
- internal/mail/router_test.go
- internal/mail/mailbox_test.go

## Test cases for router
1. Route() resolves addresses correctly
2. Route() handles rig/role format
3. Route() handles rig/crew/name format
4. Invalid addresses return error

## Test cases for mailbox
1. Send() writes message to mailbox
2. Inbox() lists messages
3. Read() retrieves message by ID
4. Delete() removes message
5. Messages persist correctly

## Acceptance criteria
- [ ] router_test.go with 4+ tests
- [ ] mailbox_test.go with 5+ tests
- [ ] Tests pass: go test ./internal/mail/...
- [ ] Coverage > 60%


Unify gt sling and gt spawn with --args support

## Summary

Complete the unification: `gt sling` becomes THE way to assign work. Remove top-level `gt spawn`.

## Current State (Partially Done)

- `gt sling` auto-spawns polecats when target is a rig
- `gt sling --args` stores args in bead (no-tmux mode, gt-vc3l4)
- `gt spawn` still exists with flags not yet in sling

## Remaining Work

### 1. Move spawn-only flags to sling

| Flag | Current | Action |
|------|---------|--------|
| `--naked` | spawn only | Move to sling |
| `--create` | spawn only | Move to sling |
| `--molecule` | spawn only | Move to sling |
| `--force` | spawn only | Move to sling |
| `--account` | spawn only | Move to sling |
| `--no-start` | spawn only | Evaluate if needed |

### 2. Remove top-level gt spawn

- Keep `gt spawn pending` as subcommand if still needed
- Remove `gt spawn` from root commands
- Update all docs and CLAUDE.md references

### 3. Unified UX Design

Target resolution (smart defaults):
```bash
gt sling gt-abc                    # Self (current agent)
gt sling gt-abc crew               # Crew worker in current rig
gt sling gt-abc gastown            # Auto-spawn polecat in rig
gt sling gt-abc gastown/Toast      # Specific polecat
gt sling gt-abc mayor              # Mayor
```

Key flags:
```bash
gt sling gt-abc --args "patch release"   # Natural language context
gt sling gt-abc --naked                  # No-tmux mode (manual start)
gt sling gt-abc --create                 # Create polecat if missing
gt sling gt-abc --molecule mol-review    # Use specific workflow
```

### 4. Update Witness/Refinery/Deacon

These agents currently use `gt spawn`. Update to use `gt sling`:
- Witness: spawning polecats for work
- Refinery: spawning merge workers
- Deacon: any spawn logic

## Acceptance Criteria

- [ ] All spawn flags available in sling
- [ ] `gt spawn` removed (or hidden/deprecated)
- [ ] Witness uses `gt sling <rig>` for polecat work
- [ ] Docs updated
- [ ] Both human and agent UX is clean


Mayor restart loop: auto-prime and mail check on attach

When mayor session cycles (after /exit, gt mayor attach reconnects), the new session lacks context.

## Current Behavior
- Mayor exits, shell script loop restarts claude
- New session starts cold - no gt prime, no mail check
- Mayor is disoriented, doesn't know prior context
- Strong 'antimemetic properties' - we discuss fixing it, then forget

## Expected Behavior
After restart, mayor should automatically:
1. Run gt prime (load role context)
2. Check gt mail inbox (find handoff messages)
3. Look for 🤝 HANDOFF messages from predecessor

## Possible Fixes
1. Startup hook in Claude Code settings that runs gt prime
2. CLAUDE.md instructions that say 'FIRST THING: run gt prime'
3. Shell script wrapper that injects context before attach
4. Modify gt mayor attach to inject prime command

## Related
- gt-vci: Mayor handoff mail template
- gt-sye: Mayor startup protocol prompting


Digest: mol-deacon-patrol

Patrol 17: All healthy


Swarm status doesn't update after task completions

During swarm bd-784c, the swarm status remained at '9% (1/11 tasks merged)' even after 5 tasks were completed and closed.

**Expected:**
Swarm status should reflect actual completion count, either by:
1. Polling issue status from beads
2. Updating when polecats close issues
3. Updating when commits are pushed to integration branch

**Impact:**
Coordinator had to manually check bd list to know actual progress.


gt crew next: Return self when only window in cycle group

## Problem
`gt crew next --session 'gt-mayor'` returns exit code 1 when the Mayor is the only window in that cycle group.

## Expected Behavior
When an agent is the only member of its cycle group (or not in any configured cycle group), `gt crew next` should return the current session itself rather than failing.

## Context
- C-b n in Mayor's session triggers this command
- Currently only rig crews have configured cycle groups
- Mayor is not part of any crew cycle group, so it should just return itself

## Fix
If no other windows exist in the cycle group, return the current session name instead of error.


Spawn inject: Enter not submitted after multiline paste

When gt spawn injects a multiline context (85+ lines), Claude Code shows
'[Pasted text #1 +85 lines]' but the prompt is not submitted.

The tmux SendKeys function does include 'Enter' but it appears to not work
for long pasted text:

```go
func (t *Tmux) SendKeys(session, keys string) error {
    _, err := t.run("send-keys", "-t", session, keys, "Enter")
    return err
}
```

Possible fixes:
1. Use tmux paste-buffer instead of send-keys for long text
2. Send Enter separately after the text
3. Use bracketed paste mode correctly

Reproduction:
```bash
gt spawn gastown/Nux --issue gt-u1j.13 --create
# Session shows pasted text but waits at prompt
```


E2E Swarm Test Epic

E2E Test: All tasks complete, swarm landed


Task A: Setup foundation


Task B: First feature


Task C: Second feature


Task D: Integration


Digest: mol-deacon-patrol

Patrol 15


Interactive prompts for destructive operations

Add interactive confirmations for destructive operations.

## Operations Needing Confirmation
- `gt swarm cancel` - Cancels active swarm
- `gt swarm land --force` - Force landing
- `gt polecat decommission` - Removes polecat
- `gt rig remove` - Removes rig
- `gt stop --all` - Stops all sessions
- `gt mail purge` - Permanently deletes mail

## Implementation Options

### Option 1: promptui library
```go
import "github.com/manifoldco/promptui"

prompt := promptui.Prompt{
    Label:     "Delete polecat Toast",
    IsConfirm: true,
}
result, err := prompt.Run()
```

### Option 2: Simple stdin
```go
func confirm(prompt string) bool {
    fmt.Printf("%s [y/N]: ", prompt)
    var response string
    fmt.Scanln(&response)
    return strings.ToLower(response) == "y"
}
```

## Bypass Flags
All confirmations skippable with --force or --yes:
```go
if !force && !confirm("Really cancel swarm?") {
    return nil
}
```

## Acceptance Criteria
- [ ] Destructive ops prompt by default
- [ ] --force or --yes bypasses
- [ ] Clear prompt text explaining action
- [ ] Non-interactive mode (piped input) auto-fails


Agent-centric dashboard view (gt dashboard)

Charmbracelet TUI for gt feed with dashboard + stream layout.

## Layout (horizontal split)

**Top panel: Agent Tree (role/town view)**
- Shows EVERY agent organized by role
- Each agent shows their MOST RECENT activity inline
- At a glance: who is doing what RIGHT NOW
- Collapsible sections

**Bottom panel: Event Stream (chronological feed)**
- Full scrollable history of events
- Most recent at top
- More detail than the tree view
- This is what you scroll through

## Visual
```
+-------------------------------------------------------------+
| GT Feed                                    Filter: all      |
+-------------------------------------------------------------+
| gastown/                           <- AGENT TREE (top)      |
|   mayor      [10:30] Dispatched gt-xyz -> Toast             |
|   witness    [10:28] Nudged polecat-3 (idle 5m)             |
|   refinery   [10:25] Merged PR #123                         |
|   crew/                                                      |
|      joe        [10:22] Completed gt-95j13                  |
|      max        [10:18] Working on gt-s6r44                 |
|   polecats/                                                  |
|      Toast      [10:30] Received gt-xyz                     |
+-------------------------------------------------------------+
| [10:30] Toast: Received molecule gt-xyz                     |
| [10:28] witness: Nudged polecat-3 after 5m idle             |
| [10:25] refinery: Merged PR #123                            |
| ...                                        <- EVENT STREAM  |
+-------------------------------------------------------------+
| j/k: scroll  /: search  f: filter  q: quit  ?: help         |
+-------------------------------------------------------------+
```

## Why this layout?
- Top answers: what is everyone doing?
- Bottom answers: what just happened?
- Together: complete situational awareness

## Replaces
- gt feed (currently just wraps bd activity)
- gt dashboard task merges into this

## Tech
- bubbletea Model with two viewports
- Tab switches focus between tree/stream
- j/k scrolls focused panel


Digest: mol-deacon-patrol

Patrol 18: clear


E2E Test: Verify mol-polecat-work spawn

Simple test task for Phase 5 E2E validation


Digest: mol-deacon-patrol

Patrol 15: Quiet


Add gt role command group with env-based role detection

# gt role Command Group

Make role detection less fragile by using env var injection instead of cwd detection.

## Env Vars
- `GT_ROLE` - authoritative role name (mayor, witness, refinery, polecat, crew)
- `GT_ROLE_HOME` - canonical home directory for the role

## Detection Precedence
1. `$GT_ROLE` env var (authoritative)
2. Fall back to cwd-based detection (legacy/manual)
3. Warn if they disagree

## Subcommands
- `gt role` / `gt role show` - show current role
- `gt role home [ROLE]` - show home dir for role
- `gt role detect` - force cwd-based detection (debugging)
- `gt role list` - list all known roles
- `gt role env` - print export statements

## Integration Points
- gt prime - show role, warn on mismatch
- gt mol status - use gt role instead of own detection
- gt handoff - preserve GT_ROLE, reset to home
- All spawners - inject GT_ROLE and GT_ROLE_HOME

## Background
Mayor wandered to refinery dir, handoff preserved it, role detection broke.
Env var injection makes role stable across cd operations.


Digest: mol-deacon-patrol

Patrol cycle 4: routine, healthy


🤝 HANDOFF: Investigate beads-sync divergence (221 files)

## Context

gt doctor now detects orphaned code on beads-sync branch. Running it shows:

  beads-sync-orphans: 221 file(s) on beads-sync not in main

This is in the gastown repo (checking from crew/max).

## Background

- Earlier today we recovered orphaned mail migration code lost in merge 96c773f
- Recently simplified architecture: all workers use mayor/rig/.beads (redirects)
- This simplification may have caused beads-sync branch to diverge unexpectedly

## Investigation Steps

1. From crew/max run: git diff main..beads-sync --stat
2. Check if beads-sync should even exist anymore (was for multi-clone sync)
3. If obsolete with redirect architecture, consider deleting it
4. If it has legitimate changes, cherry-pick or merge to main

## Key Question

With all workers using mayor/rig/.beads via redirects, is beads-sync still needed?

## Commands

git log main..beads-sync --oneline | head -20
git diff main..beads-sync -- *.go | head -100


Show actor on pinned/status change events

Pinned events currently show no actor:

  [10:22:25] → gt-95j13 → pinned · Add tmux hotkey...

Should show who pinned it:

  [10:22:25] → gt-95j13 → pinned · Add tmux hotkey... @gastown/crew/joe

Part of epic gt-u7dxq


Human escalation path design

Flesh out the human escalation mechanism for Gas Town errors. Currently: errors mail Mayor, Mayor startup prompts about escalations. Need: structured escalation channel, escalation severity levels, and clear documentation. All edge cases in molecular algebra can write warnings to this channel.


gt swarm is implemented but undocumented

internal/swarm/ package is fully implemented with:
- gt swarm create
- gt swarm status
- gt swarm list
- gt swarm land
- gt swarm cancel
- gt swarm start

But no documentation exists for it:
- Not in README
- Not in architecture.md (uses different terminology)
- Not in any role prompts

Either:
1. Document gt swarm as the canonical mechanism
2. Or deprecate it in favor of gt sling

Related to gt-6n13 (competing molecule mechanisms)


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

Patrol 6: All healthy


test-agent-verify


Polecat template: remove redundant 'Finding Work' section

The 'Finding Work' section (bd ready, bd list, bd show) is general-purpose guidance that may not apply to polecats who are spawned with specific work. Either remove for polecats or clarify this is for discovering additional work during execution.


Create activity aggregator

Component that connects to multiple rig beads daemons and merges their activity into a unified view. Polls GetMutations and GetWorkerStatus from each rig, groups by rig/worker. Handles connection failures gracefully.

BLOCKED BY (Beads rig):
- bd-gqxd: Enrich MutationEvent with title and assignee
- bd-l13p: Add GetWorkerStatus RPC endpoint
- bd-0oqz: Add GetMoleculeProgress RPC endpoint


Digest: mol-deacon-patrol

Patrol 7: All clear


Merge: gt-h6eq.3

branch: polecat/dag
target: main
source_issue: gt-h6eq.3
rig: gastown


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


Digest: mol-deacon-patrol

Patrol 17: Quiet


Mail coordination should use town-level database

gt mail send/inbox should use ~/gt/.beads (town root) not rig-local beads. Cross-rig mail coordination (Witness <-> Mayor, polecat <-> Witness) needs to be in a shared location.


Day 3.6: Polecat closes steps for activity feed

**REVISED**: Step completion is for visibility, not session control.

Polecats close molecule steps as they complete them:
```bash
# After completing implement step:
bd close <step-bead-id>  # Or: mol step done implement
```

This provides:
1. **Activity feed visibility** - Observers see progress in real-time
2. **Audit trail** - Step completion timestamps in beads
3. **Stuck detection** - Witness can see 'long time on same step'

What this does NOT do:
- Trigger session recycle (polecat self-manages)
- Block next step (polecat continues immediately)
- Require Witness intervention

Implementation options:
- Option A: Polecat runs `bd close <step-id>` manually
- Option B: Formula `on_complete` hook auto-closes step bead
- Option C: `mol step done <step>` convenience command

Priority lowered: Nice-to-have for visibility, not launch-blocking.

**Dependency removed**: No longer depends on gt-zb0io (recycle between steps).


Digest: mol-deacon-patrol

Patrol 15: healthy


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

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


Digest: mol-deacon-patrol

Patrol 17: All agents healthy


Digest: mol-deacon-patrol

Patrol 4: All healthy, no messages


Swarm learning: Refinery merge queue automation

Manually merging 15 polecat branches was painful and error-prone. Refinery should automate: detect completed work, run tests, merge to main, handle conflicts. This is core Refinery value prop.


Swarm learning: Spawn should auto-notify polecats

town spawn assigns issues but doesn't notify polecats. Required separate 'town session send' to inject prompts. This should be one atomic operation - spawn assigns AND pokes the polecat to start working.


Self-test

Testing gt mail works


Digest: mol-deacon-patrol

Patrol #8: Stable


Merge: gt-4ev4

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


Digest: mol-deacon-patrol

Patrol #20: Stable, handoff threshold reached


Digest: mol-deacon-patrol

Patrol cycle 12: routine


Digest: mol-deacon-patrol

Patrol 19: routine


Remove dead code: splitLines first loop, unused methods.

## Dead code locations

### 1. internal/cmd/polecat.go (lines 1093-1106)
splitLines function has unreachable first loop:
```go
func splitLines(s string) []string {
    var lines []string
    for _, line := range filepath.SplitList(s) {  // DEAD: wrong function
        ...
    }
    lines = nil  // Discards above
    for _, line := range strings.Split(s, "\n") {  // This is what runs
        lines = append(lines, line)
    }
    return lines
}
```
**Fix:** Remove first loop and reset.

### 2. internal/townlog/logger.go (lines 277-279)
```go
func (e Event) JSON() ([]byte, error) {
    return json.Marshal(e)
}
```
**Fix:** Remove unused method.

### 3. internal/lock/lock.go (line 27)
```go
ErrStaleLock = errors.New("stale lock detected")
```
**Fix:** Remove unused error variable.

### 4. internal/witness/types.go (line 19)
```go
StatePaused State = "paused"
```
**Fix:** Remove unused state constant.

### 5. internal/refinery/manager.go (lines 527-538)
```go
func (m *Manager) getTestCommand() string { ... }
```
**Fix:** Remove unused method.

## Acceptance criteria
- [ ] polecat.go: Dead loop removed from splitLines
- [ ] townlog/logger.go: Event.JSON() method removed
- [ ] lock/lock.go: ErrStaleLock removed
- [ ] witness/types.go: StatePaused removed
- [ ] refinery/manager.go: getTestCommand removed
- [ ] go build ./... passes
- [ ] go test ./... passes


Digest: mol-deacon-patrol

Patrol 12: Quick cycle, all quiet


Day 2.4: Add timeout fallback for dead agents

For truly dead agents that can't report their own death:
- Daemon tracks last_seen timestamp from heartbeats
- If no heartbeat for N minutes AND state=running, mark state=dead
- This is fallback only, not primary state source

Parent: gt-d0jqp


Add bulk polecat remove command (gt polecat remove --all)

When decommissioning a rig, need to remove multiple polecats one at a time. A --all or --rig flag would allow: gt polecat remove --rig gastown --force


mol-polecat-lease

Semaphore tracking a single polecat's lifecycle.
Vars: {{polecat}}, {{issue}}

Used by Witness to track polecat lifecycle during patrol. The Witness bonds
this proto for each active polecat, creating a lease that tracks the polecat
from spawn through work to cleanup.

## Step: boot
Spawned. Verify it starts working.

Check if the polecat is alive and working:
```bash
gt peek {{polecat}}
```

If idle for too long, nudge:
```bash
gt nudge {{polecat}} "Please start working on your assigned issue."
```

Timeout: 60s before escalation to Mayor.

## Step: working
Actively working. Monitor for stuck.

The polecat is processing its assigned issue ({{issue}}).
Monitor via peek. Watch for:
- Progress on commits
- Status updates in beads
- SHUTDOWN mail when done

Wait for SHUTDOWN signal from the polecat.
Needs: boot

## Step: done
Exit received. Ready for cleanup.

The polecat has completed its work and sent SHUTDOWN.
Perform cleanup:
```bash
gt session kill {{polecat}}
gt worktree prune {{polecat}}
```

Update beads state and close the lease.
Needs: working


boot

Spawned. Verify the polecat starts working.

Check if the polecat is alive and working:
```bash
gt peek {{polecat}}
```

If idle for too long (>60s), nudge:
```bash
gt nudge {{polecat}} "Please start working on your assigned issue."
```

Timeout: 60s before escalation to Mayor.
Variables: {{polecat}}, {{issue}}


working

Actively working. Monitor for stuck.

The polecat is processing its assigned issue ({{issue}}).
Monitor via peek. Watch for:
- Progress on commits
- Status updates in beads
- SHUTDOWN mail when done

Wait for SHUTDOWN signal from the polecat.
Variables: {{polecat}}, {{issue}}


done

Exit received. Ready for cleanup.

The polecat has completed its work and sent SHUTDOWN.
Perform cleanup:
```bash
gt session kill {{polecat}}
gt worktree prune {{polecat}}
```

Update beads state and close the lease.
Variables: {{polecat}}, {{issue}}


CLI: cleanup commands for stale state

Cleanup commands for recovering from stale state.

## Commands

### gt cleanup <polecat>
Clean stale state for specific polecat.
```
gt cleanup <rig>/<polecat> [--dry-run]
```

Actions:
- Remove orphaned state.json if clone missing
- Clear stale session references
- Reset stuck state (working → idle after timeout)

### gt cleanup --all
Clean all polecats in workspace.
```
gt cleanup --all [--dry-run]
```

## Implementation
```go
func CleanupPolecat(rigName, polecatName string, dryRun bool) (*CleanupResult, error)

type CleanupResult struct {
    OrphanedStateRemoved bool
    SessionsCleared      int
    StateReset           bool
    Warnings             []string
}
```

## Overlap with Doctor
- Doctor diagnoses and offers --fix
- Cleanup is more aggressive state recovery
- Consider merging into doctor --fix

## New File
internal/cmd/cleanup.go

## Acceptance Criteria
- [ ] Removes orphaned state files
- [ ] Clears stale session refs
- [ ] --dry-run shows what would happen
- [ ] Reports all actions taken


Digest: mol-deacon-patrol

Patrol 3: quiet, health OK


Digest: mol-deacon-patrol


Merge conflicts: Buzzard/mq-status, Dementus/harness-docs


Inconsistent error wrapping patterns

Error handling is inconsistent across the codebase:

1. Some functions use fmt.Errorf with %w for wrapping, others don't
2. return nil, nil patterns (40+ occurrences) sometimes represent 'not found' and sometimes 'error but continue' - should use sentinel errors
3. Some places return nil for errors when they should propagate them

Examples of nil,nil that might need review:
- internal/git/git.go:272, 308
- internal/crew/manager.go:227
- internal/witness/manager.go:517, 523, 530, 775
- internal/beads/beads.go:225, 492


Test message

Testing GGT mail integration


Test: Polecat lifecycle validation (auto-close)

Simple test task: Read this issue, print 'Lifecycle test passed', then close this issue with bd close. No code changes needed.


list: static mailing list lookup

Static mailing list support via config file.

## Deliverables

1. Load lists from ~/gt/config/lists.json
2. Parse list:name syntax in router
3. Fan-out at send time (same as @group)
4. Error handling for unknown list names

## Example
```bash
gt mail send list:oncall -s "Alert" -m "System down"
# Expands to: mayor/, gastown/witness, beads/witness
# Creates 3 message copies
```

## Dependencies
- Config directory (gt-i6jvc)

## Acceptance
- list:oncall resolves to configured members
- Each member gets own message copy
- Unknown list returns clear error


Digest: mol-deacon-patrol

Patrol 19: all healthy


Plugin surface for daemon lifecycle hooks

Allow rigs to customize daemon behavior via hooks/plugins.

## Hook Points

- on_heartbeat: Called during daemon heartbeat cycle
- on_worker_idle: Called when worker goes idle
- on_worker_stuck: Called when stuck detection triggers
- on_lifecycle_request: Called before processing lifecycle

## Configuration

```
<rig>/config/daemon-hooks.json
{
  "on_heartbeat": "./hooks/check-ci-status.sh",
  "on_worker_idle": "./hooks/maybe-assign-work.sh",
  "idle_threshold": "5m",
  "custom_signals": [
    {"name": "ci_status", "command": "./hooks/get-ci.sh"}
  ]
}
```

## Signal Contribution

Hooks can return signals that feed into decision engine:
- SKIP_POKE: Don't poke this agent
- FORCE_POKE: Override backoff, poke now
- CUSTOM_DATA: Extra context for logging

## Use Cases

- Check CI status before interrupting test runs
- Auto-assign work when worker becomes idle
- Custom stuck detection for specific workflows


init.go: Replace custom contains() with strings.Contains


Digest: mol-deacon-patrol

Patrol 4: all clear


gt uninstall: Clean removal of Gas Town harness

Add 'gt uninstall' command to cleanly remove a Gas Town installation.

Should:
- Remove harness directory structure
- Optionally preserve rigs/data with --keep-data flag
- Warn about running sessions
- Clean up any global config references


Digest: mol-deacon-patrol

Patrol complete: 12 agents healthy, no lifecycle requests, 1 potential orphan (bd-llfl). Mayor has 6 pending messages.


Digest: mol-deacon-patrol

Patrol 14: routine


gt mail inbox doesn't find crew worker mail - identity mismatch

## Problem

Crew workers don't see their handoff messages when running `gt mail inbox` from their working directory.

## Root Cause

gt derives identity from cwd path, but crew workers have a different path structure:
- **cwd**: `/Users/stevey/gt/beads/crew/dave`
- **gt derives**: `beads/crew/dave` (wrong)
- **should be**: `beads/dave` (crew workers use `rig/name` format)

Messages sent to `beads/dave` don't show up because gt is looking for `beads/crew/dave`.

## Workaround

Use explicit identity flag:
```bash
gt mail inbox --identity "beads/dave"
```

## Fix

Identity detection in gt should handle crew/ subdirectory:
- Path `<rig>/crew/<name>` should derive identity as `<rig>/<name>`
- This matches how polecats work: `<rig>/polecats/<name>` → `<rig>/<name>`

## Affected

All crew workers in all rigs.


Silent error handling with _ = err patterns

Multiple locations intentionally ignore errors with comments like 'Ignore errors'. While some are valid (best-effort operations), others should be audited:

- witness/manager.go:542 - Ignores cmd.Run() error
- refinery/manager.go:411, 438, 509 - Ignores loadState and git pull errors
- swarm/manager.go:47 - Ignores getGitHead error
- polecat/manager.go:69, 284 - Ignores pool.Load and DeleteBranch errors
- swarm/integration.go:101, 137 - Ignores git pull and push errors

Each should be evaluated: log it, handle it, or confirm ignoring is intentional.


Digest: mol-deacon-patrol

Patrol 6: Core healthy. Noted Mayor escalation (rig mismatch) - not Deacon work.


bd sync: Handle mol-* prefix for protos gracefully

When bd sync imports protos (mol-*), it warns about prefix mismatch. The allowed_prefixes config doesn't seem to apply to imports.

Current behavior: bd sync fails import step with prefix mismatch error
Expected: mol-* should be recognized as valid proto prefix, or allowed_prefixes should be respected

Workaround: The export/push still succeeds, only import fails.

Related: bd-47qx


Digest: mol-deacon-patrol

Patrol 10


Digest: mol-deacon-patrol

P17: stable


Digest: mol-deacon-patrol

Patrol 13


Error handling improvements: retry logic and recovery hints

Improve error handling across GGT codebase.

## Issues Found

### 1. Silent Failures in Refinery
manager.go ProcessMR():
- git pull errors ignored
- Continues processing even on partial failures

### 2. Missing Beads CLI
Many operations silently continue if `bd` not found:
```go
// Current
tasks, err := m.loadTasksFromBeads(epicID)
if err != nil {
    // Non-fatal - swarm can start without tasks
}

// Better
if err != nil {
    return nil, fmt.Errorf("beads required: %w", err)
}
```

### 3. No Retry Logic
Network/lock errors should retry:
```go
func withRetry(attempts int, delay time.Duration, fn func() error) error {
    for i := 0; i < attempts; i++ {
        if err := fn(); err == nil {
            return nil
        }
        time.Sleep(delay)
    }
    return fmt.Errorf("failed after %d attempts", attempts)
}
```

### 4. Recovery Hints
Error messages should include fix suggestions:
```go
// Current
return fmt.Errorf("polecat not found")

// Better
return fmt.Errorf("polecat '%s' not found. Use 'gt polecat list' to see available polecats", name)
```

## Domain Error Types
```go
type SessionError struct {
    Op      string
    Polecat string
    Err     error
}

func (e *SessionError) Error() string {
    return fmt.Sprintf("session %s for %s: %v", e.Op, e.Polecat, e.Err)
}
```

## Files to Review
- internal/refinery/manager.go
- internal/swarm/manager.go
- internal/session/manager.go
- All cmd/*.go files

## Acceptance Criteria
- [ ] No silent error swallowing
- [ ] Retry logic for transient failures
- [ ] Helpful error messages with hints
- [ ] Consistent error types per domain


Digest: mol-deacon-patrol

Patrol 3: all healthy


Account management for multi-account Claude Code usage

Enable Gas Town to manage multiple Claude Code accounts (e.g., personal vs work) with easy switching. Core mechanism: CLAUDE_CONFIG_DIR env var per account. See docs/design/account-management.md for full design.


Epic: Async Gates for Agent Coordination

## Summary

Agents need an async primitive for waiting on external events (CI completion,
API responses, human approval). Currently they either poll wastefully or cant
resume after handoff.

## Design: Deacon-Managed Gates

### Core Concepts

**Gate** = wisp issue that blocks until external condition is met
- Type: `gate`
- Phase: wisp (never synced, ephemeral)
- Assignee: `deacon/` (Deacon monitors it)
- Fields: `await_type`, `await_id`, `timeout`, `waiters[]`

**Await Types:**
- `gh:run:<id>` - GitHub Actions run completion
- `gh:pr:<id>` - PR merged/closed
- `timer:<duration>` - Simple delay (e.g., "5m", "1h")
- `human:<prompt>` - Human approval required
- `mail:<pattern>` - Wait for mail matching pattern

### Commands

```bash
bd gate create --await <type>:<id> --timeout <duration> --notify <addr>
bd gate show <id>
bd gate list
bd gate close <id> --reason "completed"
bd gate wait <id> --notify <addr>
```

## Children (suggested breakdown)

1. Add `gate` issue type to beads
2. Add gate fields: await_type, await_id, timeout, waiters
3. Implement `bd gate create/show/list/close/wait` commands
4. Add gate checking to Deacon patrol loop
5. Implement await type handlers (gh:run, gh:pr, timer, human, mail)
6. Add gate timeout tracking and notification
7. Integration test: agent waits for CI via gate

## Open Questions

- Should gates live in wisp storage or main storage with wisp flag?
- Do we need a gate catalog (like molecule catalog)?
- Should `waits-for` dep type work with gates?


Digest: mol-deacon-patrol

Patrol 1: inbox clear, witness/refinery healthy, no orphans, no plugins


Update harness beads redirect for GGT

Change ~/ai/.beads/redirect from mayor/rigs/gastown/.beads to gastown/mayor/.beads for the GGT directory structure


Wire polecat-CLAUDE.md template into polecat spawn

The templates/polecat-CLAUDE.md file needs to be copied into each polecat worktree when spawned.

Location: templates/polecat-CLAUDE.md
Target: polecats/<name>/CLAUDE.md (with {{rig}} and {{name}} substituted)

Implementation:
- Update gt polecat spawn (or wherever worktrees are created)
- Template substitution for {{rig}}, {{name}} variables
- Ensure file is created before Claude session starts


Architecture: beads config and direct landing docs

Added to architecture.md:
- Beads multi-agent configuration table (daemon, worktree, sync-branch)
- ASCII directory layout for non-mermaid rendering
- Direct landing workflow (bypass merge queue)
- Design decisions 9 and 10 for direct landing and daemon awareness
- CLI commands for gt land


Plugin: plan-oracle (work decomposition)

Plugin that helps decompose epics/issues into sub-tasks. Analyzes scope, identifies dependencies, estimates complexity for parallelization, creates beads for sub-tasks with dependency links.


Standardize wisp creation syntax across role templates

## Task

Role templates use inconsistent syntax for creating wisps.

## Current State

**Deacon template:**
```bash
bd mol wisp create mol-deacon-patrol
bd update <wisp-id> --status=pinned --assignee=deacon
```

**Witness template (BROKEN - see gt-xxx):**
```bash
bd mol wisp mol-witness-patrol --assignee={{ .RigName }}/witness
```

## Recommended Pattern

All patrol roles should use the same two-step pattern:
```bash
bd mol wisp create mol-<role>-patrol
bd update <wisp-id> --status=pinned --assignee=<identity>
```

Or we should add `--assignee` flag to `bd mol wisp` (file in beads repo if preferred).

## Templates to Update

- witness.md.tmpl (broken, needs immediate fix)
- Verify consistency in refinery.md.tmpl if it also creates wisps

## Related

This is a consistency task; the witness template bug is tracked separately as P0.


Digest: mol-deacon-patrol

Patrol 3: all healthy, mayor running, witnesses running


Feed daemon: curate raw events into user-facing feed

Goroutine in gt daemon that transforms raw events into curated activity feed.

## Input
- Tails ~/gt/.events.jsonl (raw events from gt, bd, agents)

## Output
- Writes ~/gt/.feed.jsonl (curated, user-facing)

## Processing
1. Filter by visibility tag (drop audit-only events)
2. Dedupe repeated updates (5 molecule updates → "agent active")
3. Aggregate related events (3 issues closed → "batch complete")
4. Future: AI summarization via haiku for complex activity

## Integration
- Runs as goroutine in existing gt daemon
- Starts when daemon starts
- Graceful shutdown on daemon stop

Part of epic gt-u7dxq


Digest: mol-deacon-patrol

Patrol 1: All agents healthy, no lifecycle requests, cleaned 3 abandoned wisps


Digest: mol-deacon-patrol

Patrol #1: No issues found. All 6 agents healthy. No orphans.


Day 2.1: Daemon reads agent bead state field

Daemon queries agent beads for state instead of inferring from PID/tmux.

Change getAgentState() to:
1. Look up agent bead by ID (gt-mayor, gt-witness, etc.)
2. Read state field (idle|running|stuck|stopped)
3. Trust the value

Parent: gt-d0jqp


Add gt decommission command for clean swarm/worker shutdown

Single command to cleanly shut down a swarm and its workers: cancel swarm, stop sessions, optionally remove polecats. E.g. gt decommission gt-hw6 --cleanup


go install may fail for new users - private repo

README shows:
  go install github.com/steveyegge/gastown/cmd/gt@latest

This fails on fresh install if repo is private:
  fatal: could not read Username for 'https://github.com'

README should either:
1. Note the repo is private (if applicable)
2. Add SSH config instructions
3. Or provide 'build from source' alternative

This will be the first command new users try.


Overhaul autonomous-mode guidance with ledger/capability framing

Re-read all relevant docs in ~/gt/docs (especially hop/) and overhaul the autonomous-mode guidance in role templates with a stronger "why" framing.

Current state:
- Theory of Operation explains "system stalls if you wait"
- Steam engine metaphor (piston, gearbox, flywheel)
- Physics not politeness language

Enhancement direction (without revealing HOP explicitly):
1. Frame work as "contributing to a ledger of demonstrated capability"
2. Emphasize quality: "your work history is visible, every completion matters"
3. Add the redemption arc: "bad work can be overcome through consistent good work"
4. Strengthen the "proving the model" angle: "every autonomous completion is evidence this works at scale"
5. Consider adding "your CV grows with every completion" concept

Files to update:
- internal/templates/roles/*.md.tmpl (all role templates)
- internal/cmd/prime.go (AUTONOMOUS MODE output)
- Possibly ~/gt/docs/philosophy.md or similar

Constraints:
- Gas Town cannot explicitly reference HOP
- Concepts and motivation are fine, just not the name or confidential details
- Should feel like natural evolution, not grafted-on messaging

Read first:
- ~/gt/docs/hop/CONTEXT.md
- ~/gt/docs/hop/BUSINESS_OVERVIEW.md
- ~/gt/docs/philosophy.md (if exists)
- All role templates

Deliverable: Updated templates and prime.go with stronger ledger/capability framing.

Implemented ledger/capability framing in all role templates and prime.go. Also fixed hooked/pinned terminology confusion. Filed gt-d9smb for gt mol status output fix.


Digest: mol-deacon-patrol

Patrol 14: routine


Test Patrol for Bonding

Parent issue for mol bond CLI test


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-3cns
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Default polecat names: Mad Max theme instead of AdjectiveNoun

Current default naming for new polecats uses AdjectiveNoun convention.
Since rigs already provide namespacing, we can use more thematic names.

Suggestion: Use Mad Max / Fury Road character and vehicle names as defaults.
Examples: Furiosa, Nux, Slit, Morsov, Toast, Rictus, Warboy, etc.

Could also include:
- War Rig parts: Guzzler, Tanker, Pursuit
- Citadel roles: Imperator, Blackthumb, Organic
- Wasteland terms: Chrome, Witness, Shiny

Implementation:
- Add name generator in internal/polecat/ or similar
- Use when --create flag is used without explicit name
- Cycle through pool to avoid duplicates within a rig


Merge: furiosa-1767059690595

branch: polecat/furiosa-1767059690595
target: main
source_issue: furiosa-1767059690595
rig: gastown

Stale merge requests - branches no longer exist


Digest: mol-deacon-patrol

Patrol #17


Merge: capable-1767074169502

attached_args: Code review this merge request

branch: polecat/capable-1767074169502
target: main
source_issue: capable-1767074169502
rig: gastown


Test Patrol Parent

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

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

Original description:
Test parent for Christmas Ornament pattern


Overseer inbox for strategic notifications

New address overseer/ for strategic notifications.

Receives:
- Convoy completions
- Cross-rig dependency resolutions
- Escalations from Deacon
- Daily digests (optional)

Separate from operational mail - this is the executive dashboard.

Related: hq-7h8jx (Convoy System epic in town beads)


Mail orchestrator daemon

Background mail orchestrator daemon.

## Command
```
gt mail orchestrate [--interval N] [--once] [--verbose]
```

## Purpose
Background process that:
1. Monitors outbox for pending mail
2. Delivers to recipient inboxes
3. Handles offline recipients (retry later)
4. Cleans delivered messages from outbox

## Why Needed?
Current mail is synchronous. If recipient is offline or mailbox locked, send fails.
Orchestrator enables async delivery with retry.

## Implementation
```go
func (o *Orchestrator) Run(interval time.Duration) error {
    ticker := time.NewTicker(interval)
    for range ticker.C {
        o.processOutbox()
    }
}

func (o *Orchestrator) processOutbox() {
    // List outbox/*.json
    // For each, attempt delivery
    // On success, delete from outbox
    // On failure, increment retry count
}
```

## Outbox Structure
```
<town>/mayor/mail/outbox/
├── msg-abc123.json
└── msg-def456.json
```

## Lower Priority
Current synchronous delivery works. Orchestrator is optimization.

## Acceptance Criteria
- [ ] Background daemon mode
- [ ] Retry failed deliveries
- [ ] --once for single pass
- [ ] Configurable interval


Digest: mol-deacon-patrol

Patrol 18: Quiet


Digest: mol-deacon-patrol

Patrol #7


Digest: mol-deacon-patrol

Patrol 2: all healthy, no callbacks


Digest: mol-deacon-patrol

Patrol cycle 7: routine, healthy


Witness Patrol

Per-rig worker monitor patrol loop with progressive nudging.

Duplicate patrol molecule beads - keeping gt-t5i07, gt-8ynws, gt-kt9qq


Digest: mol-deacon-patrol

Patrol 5: all clear


Digest: mol-deacon-patrol

Patrol 11: Nominal


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

Patrol 7: All healthy


Polecat template: clarify work status commands (bd list vs gt mol status)

Template shows 'bd list --status=in_progress' for checking work, but polecats should probably use 'gt mol status' instead (or in addition). Clarify the right approach for polecats to check their current work assignment.


Blocked issues: gt-um6q, gt-lz13, gt-5xph depend on missing beads features

Template/docs updates blocked on: bd-nurq (bd mol current), bd-29fb (bd close --continue). These gastown issues should be marked blocked on the beads issues once cross-rig deps work.


Implement gt watch command scaffold

Basic bubbletea TUI scaffold for 'gt watch' command. Discovers rigs, connects to daemons, renders placeholder view. Foundation for the full activity feed TUI.


gt feed: Activity feed command with tmux-aware modes

## Context

`bd activity` exists and works well for streaming beads mutation events. However:
- It's not discoverable via `gt` (the agent coordination CLI)
- No tmux-aware behavior for when Gas Town is running in tmux
- The planned TUI (gt-rivr) was tombstoned - need a simpler approach

## Requirements

### Without tmux (standalone mode)
- `gt feed` streams activity to stdout (like `bd activity --follow`)
- Supports filtering by rig, time window, event type
- Works in any terminal

### With tmux (integrated mode)
- Could open/attach to a dedicated activity pane
- Or provide a way to send feed to a specific pane
- Integrate with existing gt tmux session management

## Design Questions

1. **Command name**: `gt feed` vs `gt activity` vs `gt watch`?
2. **Tmux integration**: Dedicated pane? Split? Popup?
3. **Cross-rig aggregation**: Merge events from multiple rig daemons?
4. **Filtering UX**: By rig, by molecule, by event type?

## Implementation Options

**Phase 1: Simple wrapper**
- `gt feed` shells out to `bd activity --follow`
- Add `--rig` flag for filtering
- Works identically with/without tmux

**Phase 2: Tmux-aware**
- Detect if running in gt tmux session
- Offer to open in dedicated pane
- `gt feed --pane` to force pane mode

**Phase 3: Cross-rig** (if needed)
- Aggregate from multiple rig daemons
- Unified activity stream across town

## Related

- gt-rivr (tombstoned) - Original TUI epic
- gt-22ng - Activity aggregator (blocked)
- bd activity command - The underlying implementation


Support numeric shortcuts in mail read (e.g., 'mail read 1')

When inbox shows numbered messages like:
* 1. gm-19b29031...  2025-12-16  mayor  Subject...
* 2. gm-19b26d51...  2025-12-16         Subject...

Users should be able to run 'gt mail read 1' instead of needing the full message ID 'gt mail read gm-19b29031f6a172206'.

Implementation:
- Track inbox message order in display
- Map numeric indices to actual message IDs
- Accept both numeric shortcuts and full IDs in 'mail read' command


Day 3.0: Document mail protocol contracts

Document the formal mail protocol for Gas Town agent coordination.

Mail Types:

**POLECAT_DONE** (polecat → witness)
```
Subject: POLECAT_DONE: <name>
Body: {"issue": "gt-xyz", "status": "complete|failed", "notes": "..."}
```

**MERGE_READY** (witness → refinery)
```
Subject: MERGE_READY: <branch>
Body: {"worker": "nux", "issue": "gt-xyz", "branch": "polecat/nux/gt-xyz"}
```

**MERGED** (refinery → witness)
```
Subject: MERGED: <branch>
Body: {"issue": "gt-xyz", "sha": "abc123", "worker": "nux"}
```

**LIFECYCLE:Shutdown/Cycle/Restart** (agent → deacon/)
```
Subject: LIFECYCLE:Shutdown
Body: {"action": "shutdown"}
```

**HELP** (polecat → witness → mayor)
```
Subject: HELP: <brief>
Body: {"issue": "gt-xyz", "problem": "...", "context": "..."}
```

Create: docs/mail-protocol.md


Digest: mol-deacon-patrol

Patrol cycle 13: All healthy


Test Patrol Parent

Test parent for Christmas Ornament pattern


Digest: mol-deacon-patrol

Patrol cycle 6: routine


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-3tssq
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Digest: mol-deacon-patrol

Patrol 2: All systems nominal


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


Digest: mol-deacon-patrol

Patrol complete: inbox clear, no gates, all agents healthy, no orphans


Digest: mol-deacon-patrol

Patrol 2: all healthy, beads swarm active


Digest: mol-deacon-patrol

Patrol 9: All green


Digest: mol-deacon-patrol

Patrol 4: routine, all healthy


Epic: Wisp Molecule Integration

## Vision

Integrate Beads wisp molecules into Gas Town. All orchestration work runs as wisp molecules - patrols, polecat workflows, batch operations. Only digests reach main beads.

## The Steam Engine Metaphor

```
Engine does work → generates steam
Steam wisps rise → execution trace
Steam condenses → digest (distillate)
Steam dissipates → cleaned up (burned)
```

## Architecture

```
Proto Molecules (templates)
    ↓ bd mol bond
Wisps (.beads-wisps/ or inline)
    ↓ bd mol squash + AI summary
Main Beads (digests only)
```

## Vocabulary

| Term | Meaning |
|------|---------|
| bond | Attach proto to work (creates wisps) |
| wisp | Temporary execution step (steam rising) |
| squash | Condense wisps into digest |
| burn | Destroy wisps without record |
| digest | Permanent condensed record (distillate) |

## Key Design Decisions

1. **Wisp location**: Per-rig or inline in main beads with wisp flag
2. **Summary generation**: Agent that did work generates summary (inversion of control)
3. **Squash timing**: Final step of molecule workflow, before signaling done
4. **Crash recovery**: Wisps persist, Witness detects stalls, new agent resumes
5. **Patrols**: Each cycle is fresh wisp molecule, squashed on completion

## Digest Contents

- Molecule type and instance ID
- Assignee, start/end times
- Source issue reference
- AI-generated summary
- Outcomes (issues closed, commits, branches)

## Integration Points

- gt rig init: Configure wisp storage
- gt spawn --molecule: Bond creates wisps
- gt prime: Show wisp molecule context
- Polecat CLAUDE.md: Summary + squash protocol
- gt doctor: Wisp health checks
- Deacon/Witness/Refinery: Patrol molecules

## Phases

Phase 1: Wisp setup infrastructure
Phase 2: Spawn integration
Phase 3: Completion flow (summary + squash)
Phase 4: Patrol integration
Phase 5: Documentation and polish


Phase 1.1: gt rig init creates .beads-ephemeral/

Add ephemeral beads repo creation to rig initialization.

## Implementation

In `gt rig init` (or equivalent setup):
1. Create `<rig>/.beads-ephemeral/` directory
2. Initialize as git repo
3. Create minimal beads config (no sync-branch needed)
4. Add to .gitignore if not already

## Config

```yaml
# .beads-ephemeral/config.yaml
ephemeral: true
# No sync-branch - ephemeral is local only
```

## Verification

```bash
gt rig init gastown
ls gastown/.beads-ephemeral/  # Should exist
```


Phase 4.2: Witness/Refinery patrol molecules

Extend ephemeral patrol pattern to Witness and Refinery.

## Witness Patrol Cycle

mol-witness-patrol-cycle:
1. scan-polecats: Check each polecat status
2. detect-stalls: Find stuck/idle polecats
3. nudge-or-escalate: Take action on stalls
4. log-status: Record cycle results
→ Squash with summary

## Refinery Patrol Cycle

mol-refinery-patrol-cycle:
1. scan-queue: Check merge queue
2. process-ready: Merge ready MRs
3. handle-failures: Deal with conflicts/failures
4. log-status: Record cycle results
→ Squash with summary

## Quiescent Mode

When no work: just log 'no activity' summary.
Witness and Refinery can sleep between cycles until triggered.


Phase 5.1: Document ephemeral architecture

Update docs with ephemeral molecule architecture.

## Files to Update

### docs/architecture.md
- Add Ephemeral Molecules section
- Diagram: Proto → Ephemeral → Digest flow
- Explain inversion of control for summaries

### docs/molecules.md (new or update)
- Proto molecule catalog
- Ephemeral vs main beads
- Molecule lifecycle
- Summary generation guidelines

### Agent CLAUDE.md files
- Polecat: molecule workflow protocol
- Deacon: patrol cycle pattern
- Witness: patrol cycle pattern
- Refinery: patrol cycle pattern

## Key Concepts to Document

1. Everything is a molecule
2. Orchestration molecules are ephemeral
3. Only digests reach main beads
4. Agents generate their own summaries
5. Crash recovery via ephemeral persistence


Phase 5.2: Ephemeral error handling and recovery

Handle edge cases in ephemeral molecule lifecycle.

## Scenarios

### Agent dies mid-molecule
- Ephemeral state persists
- Witness detects stall (no heartbeat)
- Options:
  a. Nudge agent to resume
  b. Reassign to new agent
  c. Escalate to Mayor

### Squash fails
- Retry with exponential backoff
- If persistent failure, escalate
- Don't lose the ephemeral state until squash succeeds

### Orphaned molecules
- Molecule started, never completed
- gt doctor detects (>24h old with no activity)
- Options:
  a. Manual review
  b. Auto-abandon with 'abandoned' digest
  c. Reassign

### Ephemeral repo corruption
- Re-init from scratch
- Active molecules are lost
- Main beads is source of truth for assigned work

## Implementation

Add error handling to:
- bd mol bond (handle init failures)
- bd squash (retry logic)
- gt doctor (recovery suggestions)


Phase 1.2: Configure bd for ephemeral molecule bonding

Ensure bd mol bond --ephemeral works with Gas Town setup.

## Questions for Dave

1. Does bd automatically find .beads-ephemeral/ or need explicit path?
2. How does bd mol bond --ephemeral know which repo to use?
3. Is there a redirect mechanism for ephemeral like main beads?

## Integration

From polecat/crew working directory:
```bash
bd mol bond mol-polecat-work --ephemeral --assignee $(gt whoami)
```

Should create molecule in rig's .beads-ephemeral/, not main beads.


Phase 1.3: gt doctor checks for ephemeral health

Add doctor checks for ephemeral beads repo.

## Checks

1. **ephemeral-exists**: .beads-ephemeral/ directory exists for each rig
2. **ephemeral-git**: It's a valid git repo
3. **ephemeral-orphans**: Molecules started but never squashed (>24h old)
4. **ephemeral-size**: Warn if ephemeral repo is >100MB (should be cleaned)
5. **ephemeral-stale**: Molecules with no activity in last hour

## Auto-fix

--fix can:
- Create missing ephemeral repo
- Clean up old completed molecules (already squashed)
- NOT auto-squash incomplete molecules (needs AI summary)


Phase 2.1: gt spawn --molecule bonds in ephemeral

Make gt spawn molecule-aware with ephemeral bonding.

## New Flag

```bash
gt spawn --issue gt-xxx --molecule mol-polecat-work
```

## Behavior

1. Create polecat with fresh worktree (existing)
2. Bond molecule in ephemeral: `bd mol bond mol-polecat-work --ephemeral`
3. Link molecule root to source issue
4. Include molecule context in work assignment mail
5. Start session

## Work Assignment Mail

```
Subject: Work Assignment: Fix lifecycle bug [MOLECULE]

You are working on gt-rixa as part of molecule mol-polecat-work.

Molecule instance: eph-abc123
Current step: read-assignment (1/8)

Follow the molecule workflow. When complete, generate summary and squash.
```


Phase 2.2: gt prime shows ephemeral molecule context

Update gt prime to detect and display ephemeral molecule state.

## Detection

1. Check for active ephemeral molecule assigned to current identity
2. Parse molecule progress (current step, total steps)
3. Show in prime output

## Output

```
🔧 Polecat furiosa, checking in.

📦 Molecule: mol-polecat-work (eph-abc123)
   Step 3/8: do-work
   Source: gt-rixa
   Started: 10 minutes ago

Run 'bd mol status' for full molecule state.
```


Phase 2.3: Polecat CLAUDE.md molecule workflow protocol

Update polecat prompting for molecule-based work.

## CLAUDE.md Updates

Add section on molecule workflow:

```markdown
## Molecule Workflow

When assigned a molecule (check gt prime output):

1. Follow molecule steps in order
2. Mark steps complete: bd mol step complete <step-id>
3. Before signaling done:
   a. Generate summary of work performed
   b. Run: bd squash <molecule-root> --summary "<your summary>"
4. Then signal done as normal

### Summary Guidelines

Your summary should include:
- What was the task?
- What did you do?
- What was the outcome?
- Any issues or follow-ups?

Keep it to 2-4 sentences. This becomes the permanent record.
```


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..."
```


Phase 3.2: mol-polecat-work squash step

Add summary+squash as final steps in mol-polecat-work.

## Current Steps

1. read-assignment
2. understand-task
3. implement-solution
4. verify-tests
5. commit-work
6. signal-done

## Updated Steps

1. read-assignment
2. understand-task
3. implement-solution
4. verify-tests
5. commit-work
6. **generate-summary** ← NEW
7. **squash-molecule** ← NEW
8. signal-done

## Step Definitions

### generate-summary
Agent writes a concise summary following the template.
Save to a local variable or temp file.

### squash-molecule
Run: bd squash $MOLECULE_ROOT --summary "$SUMMARY"
This creates digest in main beads, cleans ephemeral.

## Update Location

This requires updating the mol-polecat-work definition in beads molecule catalog.


Phase 4.1: mol-deacon-patrol uses ephemeral

Deacon patrol cycles run as ephemeral molecules.

## Current Deacon Loop

```
while running:
    check_heartbeat()
    check_mail()
    sleep(interval)
```

## Molecule-Based Loop

```
while running:
    mol = bd mol bond mol-deacon-patrol-cycle --ephemeral
    execute_cycle(mol):
        check_heartbeat()
        check_mail()
        log_status()
    summary = generate_cycle_summary()
    bd squash mol --summary summary
    sleep(interval)
```

## Benefits

- Each cycle is tracked
- Digests show daemon health over time
- Can query: 'show me patrol cycles from last hour'
- Crash mid-cycle → ephemeral shows where we were


Update Refinery to use Beads merge queue

Replace branch discovery with Beads queue in the Refinery module:

Current (internal/refinery/manager.go):
- Scans for polecat/* branches
- Creates MR objects on-the-fly

New:
- Pull from Beads: bd ready --type=merge-request
- Process each MR
- Close with merge commit: bd close <id> --reason="Merged at <sha>"
- Handle failures: bd update <id> --status=blocked --reason="..."

The Engineer (agent) becomes Beads-native.
The Refinery (module) provides the infrastructure.


Engineer main loop: poll for ready merge-requests

Implement the Engineer's main processing loop.

Loop structure:
1. Query: bd ready --type=merge-request
2. If empty: sleep(poll_interval), continue
3. Select highest priority, oldest MR
4. Claim: bd update <id> --status=in_progress
5. Process (delegate to other subtasks)
6. Repeat

Configuration:
- poll_interval: from rig config (default 30s)
- max_concurrent: from rig config (default 1)

The loop should be interruptible and handle graceful shutdown.

Reference: docs/merge-queue-design.md#engineer-processing-loop


Fetch and conflict check: git operations for MR

Implement git operations for MR processing.

Steps:
1. git fetch origin <mr.branch>
2. git checkout <mr.target> (main or integration/xxx)
3. git merge --no-commit --no-ff <mr.branch> (test merge)
4. Check for conflicts
5. If conflicts: abort and return Failure(conflict, files)
6. If clean: abort (actual merge in next step)

Helper functions:
- FetchBranch(branch string) error
- CheckConflicts(source, target string) ([]string, error)

Reference: docs/merge-queue-design.md#process-merge-steps


Merge execution: merge, test, push

Implement the actual merge execution.

Steps:
1. git checkout <mr.target>
2. git merge <mr.branch> --no-ff -m 'Merge <branch>: <title>'
3. If config.run_tests:
   - Run test_command (from config)
   - If failed: git reset --hard HEAD~1, return Failure(tests_failed)
4. git push origin <mr.target>
5. Return Success(merge_commit=HEAD)

Configuration:
- run_tests: bool (default true)
- test_command: string (default 'go test ./...')

Handle push failures with retry logic.

Reference: docs/merge-queue-design.md#process-merge-steps


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


Success handling: close MR, close source issue, cleanup

Handle successful merge completion.

Steps:
1. Update MR with merge_commit SHA:
   bd update <id> --body='...\nmerge_commit: <sha>'
2. Close MR with reason:
   bd close <id> --reason='merged'
3. Close source issue (the work item):
   bd close <source_issue> --reason='Merged in <mr_id>'
4. Delete source branch (if configured):
   git push origin --delete <mr.branch>
5. Log success

Configuration:
- delete_merged_branches: bool (default true)

Reference: docs/merge-queue-design.md#process-merge-steps