beads: Stop searching upward when .beads found

## Problem

When running bd commands in a nested directory structure with multiple .beads directories, bd shows a confusing warning:

```
╔══════════════════════════════════════════════════════════════════════════╗
║ WARNING: 2 beads databases detected in directory hierarchy              ║
╠══════════════════════════════════════════════════════════════════════════╣
║ Multiple databases can cause confusion and database pollution.          ║
║                                                                          ║
║   /Users/stevey/gt/gastown/.beads (261 issues)                           ║
║   /Users/stevey/gt/.beads (21 issues)                                    ║
║                                                                          ║
║ WARNING: Not using the closest database! Check your BEADS_DB setting.   ║
║                                                                          ║
║ RECOMMENDED: Consolidate or remove unused databases to avoid confusion. ║
╚══════════════════════════════════════════════════════════════════════════╝
```

## Why This Is Wrong

In Gas Town, nested .beads directories are **intentional and necessary**:
- Town level: /Users/stevey/gt/.beads (mail, town-level issues)
- Rig level: /Users/stevey/gt/gastown/.beads (gastown project issues)
- Worker level: polecats have their own beads in worktrees

These are **unrelated** beads instances for different scopes. They should never be consolidated.

## Expected Behavior

When bd finds a .beads directory, it should:
1. Use that directory (closest ancestor wins)
2. **Stop searching upward** - do not look for parent .beads directories
3. **No warning** about multiple databases

## Current Behavior

bd searches all the way up to root, finds all .beads directories, and warns about "multiple databases" even though they are separate, intentional instances.

## Fix

In the database discovery code, stop the upward search as soon as a .beads directory is found. The first .beads found is the one to use, and parent directories are out of scope.

## Note

This is a beads issue, filed here for tracking. Should be implemented in the beads codebase.


Witness: close arm when polecat completes

When witness cleans up a polecat, close its mol-polecat-arm issue.

## Changes to witness/manager.go

In cleanupPolecat():
1. Get arm ID from handoffState.WorkerStates[name].ArmID
2. If exists, call: bd close {armID} --reason='polecat cleaned up'
3. Clear ArmID from handoff state

## Arm Close Reasons

- 'polecat cleaned up' - normal completion
- 'polecat killed - stuck' - killed due to inactivity
- 'polecat killed - escalated' - killed after Mayor escalation

## State Update

The arm's description could be updated with final outcome before closing.
Needs: gt-59zd.4


gt-refinery-gastown

Refinery - per-rig merge queue processor for gastown.

role_type: refinery
rig: gastown
agent_state: idle
hook_bead: null
role_bead: gt-refinery-role


Work reconciliation module

Port reconcile.py work verification to Go.

## Purpose

Verify assigned issues are completed before landing.

## Interface

```go
type ReconcileResult struct {
    CompletedIssues  []IssueInfo
    IncompleteIssues []IssueInfo
    AllComplete      bool
    PolecatsChecked  []string
    Errors           []string
}

func ReconcileWork(rig string, polecats []string) *ReconcileResult
func GetAssignedIssues(assignee string) []IssueInfo
func UnassignIssue(issueID string, resetStatus bool) error
```

## Logic

1. Get list of polecats in swarm
2. For each polecat, query beads for assigned issues
3. Categorize as completed (closed) or incomplete (open/in_progress)
4. Return summary for landing decision

## Handling Incomplete Work

If issues incomplete:
- Abort landing (default)
- Or force landing (leaves work unfinished)
- Unassign incomplete issues for future work

## Reference

PGT: swarm/reconcile.py


Agent scanner utility for filesystem

Filesystem scanner to discover agent directories in a rig or town.

## Deliverables

1. Function: ScanRigAgents(rigPath) -> []AgentAddr
   - Finds: witness/, refinery/, crew/*, polecats/*
   - Returns normalized addresses (e.g., "gastown/witness")

2. Function: ScanTownAgents(townPath) -> []AgentAddr
   - Iterates all rigs, calls ScanRigAgents for each
   - Returns all agent addresses in town

3. Alias resolution:
   - @rig/gastown → ScanRigAgents("gastown")
   - @town → ScanTownAgents()
   - @witnesses → filter for */witness across all rigs
   - @crew/gastown → filter crew/* in gastown

## Location
internal/discovery/scanner.go (new package)

## Acceptance
- Scanner finds all agent types
- Alias patterns resolve correctly
- Unit tests pass


gt spawn: Notify Deacon and Witness on polecat start

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

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

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

Part of the village self-monitoring architecture.


Implement context-checking for agent sessions

Implement the context-checking step that allows agents to assess their remaining context capacity.

## Challenge

Agents don't have direct access to token counts. Need heuristics:

### Approach 1: Message count heuristic
- Count messages in conversation
- Estimate tokens per message
- Compare to model's context window

### Approach 2: External tool
- Claude Code could expose a /context command
- Returns estimated usage percentage
- Agent queries before each work item

### Approach 3: Conservative fixed limits
- After N work items, always handoff
- Simple but may waste context or handoff too early

### Approach 4: Hook-based injection
- SessionStart hook injects context estimate
- Updated periodically via tool call

## Recommendation

Start with Approach 3 (fixed limits) as MVP:
- Default: 3-5 work items per session
- Agent can override via variable
- Upgrade to smarter heuristics later

## Integration

- Add check-context step to mol-ready-work
- Implement handoff trigger logic
- Test with various context states


Digest: mol-deacon-patrol

Patrol #2: All healthy, no changes


Add await-work and plugin-run steps to mol-refinery-patrol

## Context

The mol-refinery-patrol needs two additional steps:

### 1. await-work (Decision Point)

Not just 'wait for signal' but a crossroads:
- Check for pending signals (mail, nudge, human)
- Check plugin gates (any plugins need to run?)
- Check maintenance schedule (daily/weekly due?)
- Evaluate context and decide next action

Position: Between burn-or-loop and inbox-check (the loop point)

### 2. plugin-run (Like Deacon)

Refinery needs plugin support for:
- **Monitors**: Flag PRs touching sensitive code
- **Gates**: Block merges under certain conditions
- **Schedulers**: Reorder queue based on priority/urgency
- **Maintenance**: Weekly cleanup, audits, stats
- **Audits**: Log merge statistics, track patterns

Position: After queue-scan, before process-branch

## Implementation

Update RefineryPatrolMolecule() in builtin_molecules.go to include:
- await-work step with decision tree
- plugin-run step with gate types

## Related
- gt-7920 (original mol-refinery-patrol)
- docs/deacon-plugins.md (existing plugin model)


gt spawn --continue for resuming parked molecules

Add `--continue` flag to gt spawn for resuming parked molecules:

```bash
gt spawn --continue gt-mol-root
```

This:
1. Finds molecule root
2. Verifies molecule is in "parked" state (in_progress, no assignee)
3. Checks external deps are now satisfied
4. Spawns polecat with molecule context
5. Polecat reads handoff mail and continues from blocked step

Part of cross-project dependency system.
See: docs/cross-project-deps.md

Depends on: gt-zniu (gt park)
Depends on Beads: bd-zmmy (bd ready resolution)


Deacon keepalive: quiet daemon during rounds

Replace tmux-poke interrupts with a keepalive file the daemon respects.

## Problem

Current daemon pokes Deacon via tmux SendKeys every ~5 minutes if heartbeat
is stale. This can INTERRUPT the Deacon mid-work, especially during long
plugin execution or health remediation.

## Solution

Deacon writes a keepalive file at start of rounds:
```json
{
  "timestamp": "2025-12-20T15:30:00Z",
  "expected_duration_minutes": 10,
  "action": "executing mol-deacon-rounds"
}
```

Daemon reads this and backs off:
- If keepalive is fresh AND within expected_duration: skip poke
- If keepalive is stale OR past expected_duration: poke (fallback)

## Files

- `{townRoot}/deacon/keepalive.json` - Written by Deacon
- Daemon already reads `{townRoot}/deacon/heartbeat.json` - similar pattern

## Deacon Behavior

1. Start of rounds: write keepalive with expected duration
2. End of rounds: write heartbeat (existing), clear/update keepalive
3. If rounds take longer than expected: Deacon gets one poke, squelches it

## Daemon Changes

Modify `pokeDeacon()` in daemon.go:
1. Check keepalive.json freshness and expected_duration
2. If within bounds: skip poke, log "Deacon active"
3. If past bounds: poke as fallback

## Worst Case

Deacon crashes mid-rounds without clearing keepalive:
- Daemon waits until expected_duration expires
- Then pokes, triggering respawn loop
- Max delay: expected_duration (configurable, default 10-15 min)

## Configuration

In pinned kernel bead:
```yaml
config:
  rounds_expected_duration_minutes: 10
```


Digest: mol-deacon-patrol

Patrol 14: All healthy, 2 crew active


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?


Go scaffolding: cmd/gt, go.mod, Cobra setup

Set up Go project structure with CLI framework.

**Stack:**
- Cobra for command/flag handling
- Lipgloss for styled terminal output

**Deliverables:**
- cmd/gt/main.go with Cobra root command
- Basic subcommands: version, help
- Lipgloss styles for status output (success, warning, error)
- go.mod with dependencies


Add bulk session stop command (gt session stop --all)

When decommissioning a rig, need to stop multiple sessions one at a time. A --all or --rig flag would allow: gt session stop --rig gastown


Digest: mol-deacon-patrol

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


mol-deacon-patrol minimal formula

Create minimal mol-deacon-patrol formula for tracer bullet.

## Simplified Patrol (v0.1)

```yaml
formula: mol-deacon-patrol-v01
description: Minimal Deacon patrol for tracer bullet.
version: 1

steps:
  - id: inbox-check
    title: Check inbox
    description: |
      Run: gt mail inbox
      Handle any messages.
      Note any spawn requests or status updates.

  - id: spawn-work
    title: Spawn polecat for ready work
    needs: [inbox-check]
    description: |
      Run: bd ready
      If work available and no polecat already working it:
        gt spawn --issue <first-ready> --rig gastown
      If no work: proceed to next step.

  - id: self-inspect
    title: Assess context and decide loop vs cycle
    needs: [spawn-work]
    description: |
      Evaluate whether to loop (reset) or cycle (handoff).

      ## Heuristics

      **Favor LOOP (bd mol reset):**
      - Context < 60%
      - No errors in this cycle
      - Patrol completed normally

      **Favor CYCLE (gt handoff):**
      - Context > 80%
      - Errors encountered
      - Been running > 1 hour without cycle
      - Model suggests refresh would help

      **Action:**
      - If LOOP: bd mol reset mol-deacon-patrol
      - If CYCLE: gt handoff -s "Deacon cycling" -m "Context: X%, cycles: N"
```

## Loop via Reset

After self-inspect, if staying:
```bash
bd mol reset mol-deacon-patrol
```

This resets all steps to pending, current_step to inbox-check.
Deacon immediately continues with fresh patrol cycle.

## Cycle via Handoff

If context high or refresh needed:
```bash
gt handoff -s "Deacon cycling" -m "Context high, cycling for fresh start"
```

Daemon respawns fresh Deacon with mol-deacon-patrol on hook.

## Location

.beads/formulas/mol-deacon-patrol-v01.formula.yaml


Polecat Mood Plugin (standard)

Standard witness plugin molecule that assesses polecat emotional state.

## Molecule Definition

```json
{
  "id": "mol-polecat-mood",
  "title": "Assess mood for {{polecat_name}}",
  "description": "Analyze captured output and determine emotional state.\n\nVars:\n- {{polecat_name}} - The polecat to assess\n- {{captured_output}} - Recent tmux capture\n\nOutput: gt polecat mood {{polecat_name}} <emoji>",
  "labels": ["template", "plugin", "witness", "tier:haiku"],
  "issue_type": "task"
}
```

## Mood Emojis

```
😺 working     Active tool calls, making progress
😸 productive  Completing tasks, tests passing
🐱 idle        Waiting at prompt, no recent activity
😼 confident   Self-reviewing, about to submit
😿 struggling  Repeated errors, test failures
🙀 stuck       No progress for 10+ min
😽 done        Work complete, requesting shutdown
😾 blocked     Explicitly waiting on dependency
```

## Bonding

During witness patrol plugin-run step:

```bash
bd mol bond mol-polecat-mood $PATROL_WISP \
  --ref mood-{{polecat_name}} \
  --var polecat_name=ace \
  --var captured_output="$TMUX_CAPTURE"
```

## Installation

```bash
bd mol install mol-polecat-mood  # From Mol Mall
```

## Customization

Fork the molecule and modify description to change assessment criteria or add custom moods. Install your fork to override.


Digest: mol-deacon-patrol

Patrol 12: routine


Digest: mol-deacon-patrol

Patrol 8


Digest: mol-deacon-patrol

Patrol 12: Nominal


Simplify Go daemon to Deacon-watcher

Refactor internal/daemon to only: (1) check deacon/heartbeat.json every 60s, (2) poke gt-deacon if stale, (3) restart Deacon and mail for help if very stale. Remove all lifecycle processing and agent poking.


Digest: mol-deacon-patrol

Patrol 2: All agents healthy, routine check


Zombie session detection for refinery/witness

A Claude session can crash or hang while still appearing as 'running' in tmux. The current IsRunning checks only verify tmux session exists, not that Claude is actually processing.

## Problem
- Refinery session might be hung (Claude crashed, infinite loop, etc.)
- tmux HasSession returns true, so auto-start doesn't trigger
- MRs pile up with no processing

## Solution Options
1. **Activity-based detection**: Check last output timestamp in tmux
2. **Heartbeat file**: Agents write timestamp to file, check staleness
3. **Prompt detection**: Look for Claude '>' prompt indicating idle/stuck

## Related
- gt-bjft (spawn auto-start) assumes IsRunning means healthy
- Witness patrol assumes running refinery is processing


Phase 1.2: Daemon attachment detection

Daemon polls Deacon's pinned bead to detect naked state.

## Implementation
- Daemon knows Deacon's pinned bead ID
- Every heartbeat cycle: bd show <pinned> --json
- Parse attached_molecule field
- If null/empty: Deacon is naked

## Actions on Naked
- Spawn mol-deacon-patrol
- Attach to Deacon's pinned
- Nudge Deacon to start

## Failsafes
- Keepalive file monitoring
- Stale detection (>10min no progress)
- Force nudge on stale

Depends: gt-rana.1


gt mail reply/thread: Conversation support

Add mail conversation features:

- gt mail reply <id> -m 'message' - Reply to a message
- gt mail thread <id> - Show all messages in a thread

Enables back-and-forth communication between agents.


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

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

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

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

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


Merge: gt-rixa

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


Digest: mol-deacon-patrol

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


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

Patrol 20: final patrol before handoff


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Test Polecat Arm

Test child for bonding pattern


bd ready --type: missing type filter for MQ integration

bd ready lacks --type flag that engineer.go expects.

## Code (internal/refinery/engineer.go)
readyMRs, err := e.beads.ReadyWithType("merge-request")

## Actual bd ready
No --type flag - only supports assignee, label, priority filters.

## Impact
Refinery can't find merge-requests in queue, so MQ doesn't process anything.

## Fix Options
1. Add --type flag to bd ready
2. Use bd list --type=merge-request --status=open instead
3. Both (ready filters for unblocked, list for all)

This is blocking the entire MQ pipeline.


mol-deacon-patrol

Mayor's daemon patrol loop.

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


mol-deacon-patrol


Find abandoned work

Find abandoned work.

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

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

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


Day 1.4b: Create Deacon agent bead

Create gt-deacon agent bead for the Deacon (daemon beacon).

The Deacon is a separate Claude Code agent from Mayor:
- Receives the ONLY mechanical daemon heartbeats in the system
- Runs town plugins, cleanup, and monitoring
- Has own top-level directory: ~/gt/deacon/
- No rig preassignment (town-level, like Mayor)
- role_type: deacon

Agent bead structure:
```yaml
id: gt-deacon
type: agent
entity_platform: gastown
entity_org: steveyegge
entity_id: deacon
hook_bead: null  # or current patrol wisp
role_bead: gt-deacon-role
state: idle
role_type: deacon
```

Must be created alongside mayor, witness, refinery agent beads.


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


**VERIFICATION GATE**: This step enforces the Beads Promise.

If tests PASSED: This step auto-completes. Proceed to merge.

If tests FAILED:
1. Diagnose: Is this a branch regression or pre-existing on main?
2. If branch caused it:
   - Abort merge
   - Notify polecat: "Tests failing. Please fix and resubmit."
   - Skip to loop-check
3. If pre-existing on main:
   - Option A: Fix it yourself (you're the Engineer!)
   - Option B: File a bead: bd create --type=bug --priority=1 --title="..."

**GATE REQUIREMENT**: You CANNOT proceed to merge-push without:
- Tests passing, OR
- Fix committed, OR
- Bead filed for the failure

This is non-negotiable. Never disavow. Never "note and proceed."

instantiated_from: mol-refinery-patrol
step: handle-failures


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


Molecule state file management

## Cross-Repo Reference

This work is tracked in beads repo as **bd-hulf**.

The gastown task gt-qvn7.2.2 is a placeholder.
Actual implementation happens in beads.

See: bd show bd-hulf (from beads/crew/dave)


Update lifecycle mail targets to deacon/

Update Mayor, Witness, and Crew handoff code to send lifecycle requests to deacon/ instead of daemon/. Update internal/cmd/handoff.go and related code.


Test patrol queue feature


Create DEACON.md role context

Create ~/gt/DEACON.md with the Deacon's role context, wake cycle instructions, and command reference. Model after existing CLAUDE.md for Mayor.


Digest: mol-deacon-patrol

Patrol #20: Final before handoff


README: Update Install section for homebrew/npm

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

But users will install via homebrew or npm. Update to show:
  brew install gastown
  # or
  npm install -g @anthropic/gastown

Also add prerequisites section (tmux, Claude Code CLI).


Digest: mol-deacon-patrol

Patrol 14: Quiet


Merge: gt-rana.2

branch: polecat/nux
target: main
source_issue: gt-rana.2
rig: gastown


Delete hook types from internal/wisp

Delete from internal/wisp/types.go:
- WispType type
- TypeSlungWork constant
- HookPrefix, HookSuffix constants
- Wisp struct
- SlungWork struct
- NewSlungWork function
- HookFilename function
- AgentFromHookFilename function

The entire file may become empty or minimal.


Digest: mol-deacon-patrol

Patrol 14: All healthy


Survey all polecats (fanout)

List polecats and bond mol-polecat-arm for each one.

```bash
# Get list of polecats
gt polecat list <rig>
```

For each polecat discovered, dynamically bond an inspection arm:

```bash
# Bond mol-polecat-arm for each polecat
for polecat in $(gt polecat list <rig> --names); do
  bd mol bond mol-polecat-arm $PATROL_WISP_ID \
    --ref arm-$polecat \
    --var polecat_name=$polecat \
    --var rig=<rig>
done
```

This creates child wisps like:
- patrol-x7k.arm-ace (5 steps)
- patrol-x7k.arm-nux (5 steps)
- patrol-x7k.arm-toast (5 steps)

Each arm runs in PARALLEL. The aggregate step will wait for all to complete.

If no polecats are found, this step completes immediately with no children.


gt mq reject: manual MR rejection

Implement 'gt mq reject <id> --reason "..."' for manual rejection.

Actions:
1. Verify MR exists and is open
2. Close MR with close_reason=rejected
3. Notify worker via mail (optional)
4. Do NOT close source issue (work not done)

Options:
- --reason REASON: required explanation
- --notify: send mail to worker

Reference: docs/merge-queue-design.md#cli-commands


Day 3.7: Witness pings Deacon for second-order monitoring

Add second-order monitoring: Witnesses monitor the Deacon.

Problem: Who monitors the Deacon? If Deacon dies, the whole town stalls.

Solution:
1. Each Witness periodically sends a ping to Deacon during patrol:
   ```bash
   gt mail send deacon/ -s "WITNESS_PING" -m "{\"rig\": \"gastown\"}"
   ```

2. Deacon patrol (inbox-check) aggregates witness pings as health signals

3. If Witness doesn't get Deacon response for 2 cycles:
   - Escalate to Mayor: "Deacon unresponsive"
   - Mayor can restart Deacon via daemon

This creates overlapping patrols:
- Deacon monitors Witnesses/Refineries
- Witnesses monitor Deacon (collectively)
- Mayor is escalation target for both

Add to mol-witness-patrol after survey-workers step.


Merge: gt-ih0s

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


Digest: mol-deacon-patrol

Patrol 4: 9 sessions healthy


load-context

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

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


Digest: mol-deacon-patrol

Patrol 18: Mayor OK, 11 sessions


mol-deacon-patrol

Mayor's daemon patrol loop.

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


mol-deacon-patrol


refinery Handoff

# Merge queue tracking
last_processed_branch: null
branches_merged_this_cycle: 0


Digest: mol-deacon-patrol

Patrol 19


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


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

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


Connection interface: Protocol for local/remote ops

Abstract interface for local vs remote (SSH) operations.

## Concept

Enable Gas Town to manage rigs on remote machines via SSH. The Connection interface abstracts whether operations happen locally or remotely.

## Interface

```go
type Connection interface {
    // Identification
    Name() string
    IsLocal() bool

    // File operations
    ReadFile(path string) ([]byte, error)
    WriteFile(path string, data []byte, perm os.FileMode) error
    MkdirAll(path string, perm os.FileMode) error
    Remove(path string) error
    Stat(path string) (os.FileInfo, error)
    Glob(pattern string) ([]string, error)

    // Command execution
    Exec(cmd string, args ...string) ([]byte, error)
    ExecDir(dir, cmd string, args ...string) ([]byte, error)

    // Tmux (for session management)
    TmuxNewSession(name, dir string) error
    TmuxKillSession(name string) error
    TmuxSendKeys(session, keys string) error
    TmuxCapturePane(session string, lines int) (string, error)
}
```

## Implementations

- LocalConnection (gt-f9x.8): Direct file/exec operations
- SSHConnection (future): Operations via SSH

## Usage

```go
func NewRigManager(conn Connection, ...) *RigManager

// Operations work the same regardless of connection type
rm.DiscoverRigs()  // uses conn.Glob, conn.ReadFile
```

## Design Notes

- Connection obtained from MachineRegistry (gt-f9x.9)
- Default is always local
- SSH connection requires machine config (host, key, user)


Digest: mol-deacon-patrol

Patrol 7: nominal


Implement pinned beads for handoff state

Add pinned bead support to beads:
- Pinned beads never close, only update
- Use for persistent state like Refinery handoffs
- bd create --pinned flag
- bd list --pinned to find them
- Update description to change state


Digest: mol-deacon-patrol

Patrol 8: All clear


Phase 5: Integration and Demo

$(cat /tmp/phase5.md)


Digest: mol-deacon-patrol

Patrol 3: Quiet, all agents healthy


Work on ga-lue: Implement Witness as Claude agent. Conver...

Work on ga-lue: Implement Witness as Claude agent. Convert from shell script to Claude agent that monitors polecats, nudges idle ones, handles escalations. When done, submit MR (not PR) to integration branch for Refinery.


gt crew at/attach: Start session in crew workspace

Implement 'gt crew at <rig>/<name>' and 'gt crew attach <name>' commands:
- Start tmux session (optional - could just print cd instructions)
- Launch claude code in the workspace
- Deliver any pending mail
- Support --no-tmux to just print directory path
- 'attach' infers rig from cwd


Chemistry UX commands from Beads

Waiting on Beads repo to implement chemistry UX sugar commands (bd pour, bd wisp, bd hook, --pour flag). These are nice-to-have polish items, not blockers for core functionality.

See: gastown/mayor/rig/docs/chemistry-design-changes.md


Digest: mol-deacon-patrol

Patrol 19: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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


MVP Cutover: GGT replaces PGT for batch work

When this is closed, stop using town and start using gt.

## Acceptance Criteria

1. gt spawn assigns issue to polecat and starts session
2. gt spawn --epic spawns workers for all epic children
3. gt session manages tmux lifecycle
4. gt send / gt inbox work for mail
5. Refinery processes merge queue with semantic merges
6. Integration branches created and landed correctly
7. gt stop --all halts all sessions
8. One successful test batch completed end-to-end

## What Must Work

- Spawn polecat with issue assignment
- Spawn workers for epic children
- Session start/stop/attach
- Mail send/inbox/read
- Refinery merge loop (semantic)
- Integration branch → main landing
- Witness cleanup protocol
- Emergency stop

## What Can Be Deferred

- Doctor checks (use PGT)
- TUI dashboard
- Plugin system
- Federation
- Ephemeral rigs
- Detailed landing reports

## Test Plan

1. Create epic with 2 tasks, spawn 2 workers
2. Verify polecats get assigned and sessions start
3. Simulate task completion
4. Verify Refinery merges to integration
5. Verify landing to main
6. Verify cleanup

## Validation

Run one real batch implementing GGT issues using GGT.

## Note

No "swarm IDs" - just spawn workers for epic, let merge queue coordinate.


Digest: mol-deacon-patrol

Patrol #19: Stable


Add molecule phase lifecycle diagram to architecture.md

Create a clear lifecycle diagram showing molecule phases:

```
                    ┌─────────────┐
                    │   Proto     │
                    │  (crystal)  │
                    └──────┬──────┘
                           │
                      bd mol bond
                           │
              ┌────────────┴────────────┐
              │                         │
              ▼                         ▼
      ┌───────────────┐        ┌───────────────┐
      │     Mol       │        │    Wisp       │
      │   (liquid)    │        │    (gas)      │
      │   durable     │        │  ephemeral    │
      │  main beads   │        │ .beads-eph/   │
      └───────┬───────┘        └───────┬───────┘
              │                        │
         bd mol squash            bd mol squash
              │                        │
              ▼                        ▼
      ┌───────────────┐        ┌───────────────┐
      │    Digest     │        │   (nothing)   │
      │ (distillate)  │        │  evaporates   │
      │  in git hist  │        └───────────────┘
      └───────────────┘
```

Also document:
- When to use Mol vs Wisp
- Mol: code review waves, epic implementation, feature work
- Wisp: orchestration, polecat work sessions, patrol loops


mol-deacon-patrol


Digest: mol-deacon-patrol

Test patrol cycle - verifying wisp flow


Delete molecules_*.go files

Remove legacy Go-defined molecules:
- internal/beads/builtin_molecules.go
- internal/beads/molecules_patrol.go
- internal/beads/molecules_session.go
- internal/beads/molecules_work.go

Update install.go to cook formulas instead of seeding Go structs.
Update catalog.go if needed.


Merge: gt-i4kq

branch: polecat/slit
target: main
source_issue: gt-i4kq
rig: gastown


Digest: mol-deacon-patrol

Patrol 9: All healthy, no messages


Digest: mol-deacon-patrol

Patrol 10: All agents healthy


Implement gt mq CLI commands

Add gt mq subcommands as sugar over bd:

- gt mq submit: Create MR for current branch
- gt mq list: Show open merge requests
- gt mq next: Show next MR ready to process
- gt mq process: Engineer processes the queue
- gt mq reorder <id> --after <x>: Change ordering via deps
- gt mq status <id>: Show MR details

All commands should work with the Beads data plane.


Implement Christmas Ornament pattern for mol-witness-patrol

Integrate dynamic bonding into mol-witness-patrol once Beads primitives are ready.

## Completed

- ✅ WaitsFor parsing (gt-odfr) - Parser now extracts WaitsFor: all-children
- ✅ mol bond command (gt-isje) - gt mol bond creates dynamic children with --var expansion
- ✅ WitnessPatrolMolecule() updated with Christmas Ornament structure (gt-tnow.1)
- ✅ PolecatArmMolecule() created for per-polecat inspection (gt-tnow.2)

## Remaining

- gt-tnow.3: Plugin hook support (P2)
- gt-tnow.4: Integration test with live polecats (P2)

## Design Docs

- docs/molecular-chemistry.md (already updated with pattern)
- docs/architecture.md (already updated with activity feed)
- gt-qflq: mol-witness-patrol design bead (updated)
- gt-dapb: mol-polecat-arm proto


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


Test4

test4 body


Digest: mol-deacon-patrol

Patrol 12: All healthy


Digest: mol-deacon-patrol

Patrol 15: All healthy


Digest: mol-deacon-patrol

P15: stable


Mol Mall: Formula marketplace and aspect composition

## Summary

A marketplace for sharing molecule formulas using GitHub as backend, plus a new
**aspect composition** capability for cooking that allows formulas to be applied
as cross-cutting transformations to existing mols.

## Key Insight

Formulas aren't just standalone workflows—they're **transformations** you can
apply to other mols. This enables patterns like:
- "Apply Rule of Five code review to any coding task"
- "Wrap any epic with security review steps"
- "Add logging/metrics to any patrol molecule"

## Architecture

```
Remote Formulas (GitHub)
        ↓ install
Local Formulas (~/.gt/formulas/ or .beads/formulas/)
        ↓ cook --with
Mols (beads, git-tracked)
        ↓ pour/sling
Execution (ephemeral or tracked)
```

## Formula Types

1. **Standalone** - Complete workflows (mol-polecat-work, mol-deacon-patrol)
2. **Aspects** - Cross-cutting concerns woven into other mols (rule-of-five)
3. **Adapters** - Wrappers that make things runnable

## Aspect Composition (New Cooking Capability)

```bash
bd cook my-epic --with rule-of-five,security-review
```

Aspects declare injection points:

```yaml
# rule-of-five.formula.yaml
kind: aspect
name: rule-of-five
version: 1.2.0

inject_after:
  tag: generates-code  # matches any step with this tag

steps:
  - id: review-correctness
    title: "Review: Correctness"
  - id: review-edge-cases
    title: "Review: Edge Cases"
  - id: review-performance
    title: "Review: Performance"
  - id: review-security
    title: "Review: Security"
  - id: review-maintainability
    title: "Review: Maintainability"
```

Injection modes:
- `inject_after: <step-id or tag>` - insert steps after
- `inject_before: <step-id or tag>` - insert steps before
- `wrap: <step-id or tag>` - insert before AND after
- `replace: <step-id or tag>` - substitute entirely

## The Mall Index

A well-known repo maps short names to full references:

```yaml
# steveyegge/gt-mall/index.yaml
formulas:
  rule-of-five:
    repo: steveyegge/gt-formulas
    path: aspects/rule-of-five.formula.yaml
    version: v1.2.0
    description: "Five-lens code review"
    tags: [review, quality]
```

Commands:
- `gt mol search review` - search the index
- `gt mol install rule-of-five` - fetch from GitHub
- `gt mol install github.com/acme/formulas/custom@v1` - direct URL

## Implementation Phases

### Phase 1: Aspect Composition (Cooking)
- Extend `bd cook` to accept `--with aspect1,aspect2`
- Aspect application during mol generation
- Local aspects in `.beads/formulas/`

### Phase 2: Mall Index
- Create gt-mall repo with index.yaml
- `gt mol search` queries the index
- `gt mol install` fetches and caches formulas

### Phase 3: Publishing
- `gt mol publish` pushes to your formula repo
- PR workflow to add to mall index

### Phase 4: Refinements
- Aspect ordering and conflict detection
- Aspect dependencies (`requires: [other-aspect]`)
- Private formula repos (enterprise)
- Local overrides/forks

## Open Questions

1. **Ordering conflicts**: Two aspects inject after same step—which goes first?
2. **Aspect dependencies**: Aspect A requires aspect B?
3. **Compile-time vs runtime**: Aspects are compile-time (baked into mol).
   Wisps remain runtime (slung dynamically).

## Deferred Until

Gas Town patrols operational. Prerequisites:
- [ ] Patrol system working (Deacon, Witness, Refinery)
- [ ] Basic spawn/work/merge cycle
- [ ] Activity feed showing work progress

Then the mall becomes valuable for sharing patrol customizations.

## Supersedes

This replaces gt-uzf2l which had the original marketplace concept but lacked
the aspect composition insight.

## Related

- Cooking system (bd cook)
- Formula definitions (.formula.yaml)
- Wisp architecture (runtime molecules)

See docs/formula_evolution.md for expanded thinking on: formula resolution hierarchy, combinators (>>, |, wrap, inject, extends), algebraic properties, higher abstractions, Mol Mall registry predictions, distribution scenarios, and open questions. The aspect composition in this design corresponds to the Wrapping (AOP) and Injection combinators in that doc.


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol 20: Final patrol, all healthy, handoff triggered


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

Patrol 11: 8 sessions OK


Pinned Beads: Ongoing concerns and anchors

Pinned beads represent persistent concerns that do not close traditionally. Stay out of bd ready. Examples: Monitor production, Weekly syncs. Implementation: pinned: true field on bead.


gt sling reports hook occupied but bd hook shows empty

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


Digest: mol-deacon-patrol

Patrol 1: All agents healthy (2W 2R). 1 orphan (gt-mol-aux assigned to dead polecat). No incidents.


Expansion operators: expand and map (macros)

Implement macro-style expansion operators:
- expand(target, template) - apply template to single step
- map(molecule, template) - apply template to all matching steps

Templates use {target} substitution for step references.
Rule of Five is the canonical example.


Merge: gt-r6td

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


Rig doctor checks: Refinery health, clones, gitignore

Rig-level doctor checks.

## Checks

### RigIsGitRepo
- Verify .git/ directory exists
- Verify git status works
- Fix: Cannot auto-fix

### GitExcludeConfigured
- Check .git/info/exclude contains Gas Town dirs
- Required entries: polecats/ witness/ refinery/ mayor/
- Fix: Append missing entries

### WitnessExists
- Verify witness/ directory exists
- Verify witness/rig/ is a git clone
- Verify witness/mail/inbox.jsonl exists
- Fix: Create structure, clone repo

### RefineryExists
- Verify refinery/ directory exists
- Verify refinery/rig/ is a git clone
- Verify refinery/mail/inbox.jsonl exists
- Fix: Create structure, clone repo

### MayorCloneExists
- Verify mayor/ directory exists
- Verify mayor/rig/ is a git clone
- Fix: Create structure, clone repo

### PolecatClonesValid
- For each polecat in polecats/:
  - Verify is a git clone
  - Verify on polecat branch
  - Warn if has uncommitted changes
- Fix: Cannot auto-fix (data loss risk)

### BeadsConfigValid (if applicable)
- If .beads/ exists, verify bd commands work
- Check beads sync status
- Warn if out of sync
- Fix: Run bd sync

## Implementation

```go
var RigChecks = []Check{
    &RigIsGitRepoCheck{},
    &GitExcludeConfiguredCheck{},
    &WitnessExistsCheck{},
    &RefineryExistsCheck{},
    &MayorCloneExistsCheck{},
    &PolecatClonesValidCheck{},
    &BeadsConfigValidCheck{},
}
```


Activity Feed TUI

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


Digest: mol-deacon-patrol

Patrol 15: routine


Digest: mol-deacon-patrol

Patrol 19: Routine


Outpost error handling: Retry logic and resilience

## Overview

Error handling and retry logic for outpost operations.

## Error Types

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

## Retry Policy

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

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

## Retry Implementation

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

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

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

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

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

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

## Outpost Health Tracking

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

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

## Config

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

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

## Files

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

## Dependencies

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


Digest: mol-deacon-patrol

Patrol 11: clear


Merge: gt-5af.5

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


Pinned beads should appear first in mail inbox

Currently bd mail inbox sorts by priority then date, but pinned beads (handoff context) should always appear at the top.

**Current behavior:**
- Pinned beads mixed in with regular mail based on priority/date

**Expected behavior:**
- Pinned beads always first in inbox (before priority sorting)
- This enables handoff beads to be the default first item an agent sees

**Implementation:**
1. In mail.go runMailInbox(), after filtering, sort pinned beads to top
2. Within pinned and non-pinned groups, maintain priority/date sort

**Related:**
- gt-r8ej: Implement pinned beads for handoff state
- gt-8h4: Pinned Beads epic

**Acceptance criteria:**
- bd mail inbox shows pinned beads first
- Pinned beads still sorted by priority/date among themselves
- Non-pinned mail sorted normally after pinned section


Digest: mol-deacon-patrol

Patrol 5: Nominal


execute-actions

Send nudges, process shutdowns, escalate as decided.

Needs: decide-actions


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

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

Variables:
- gt-test123 - The source issue ID being worked on


Test gate for verification


Polecat name pooling: Bounded reusable names

Polecats reuse names from a bounded pool (50) with overflow to sequence numbers.

## Naming Scheme
- Pool: polecat-01 through polecat-50 (prefer low numbers)
- Overflow: <rigname>-<sequenceNumber> (e.g., beads-51, gastown-52)

## Design
- Witness tracks which pool names are in use
- On spawn: pick first available from pool
- If pool exhausted: use rigname-N format
- On completion: pool name returns, sequence numbers don't

## Why?
- User experience: tmux sessions survive polecat restarts
- Users stay attached, see new polecat start (like mayor respawn loop)
- Bounded resource usage for common case
- Scales beyond 50 when needed

## Implementation
- Witness maintains name allocation in beads or local state
- Tmux session runs respawn loop (like mayor)
- Name released on graceful exit or when witness detects dead session


Digest: mol-deacon-patrol

Patrol 15: All healthy


Merge: gt-y5o

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


gt mol step done: Auto-continue molecule on step completion

## Summary

Implement `gt mol step done <step-id>` command that enables polecats to close a molecule step and automatically continue to the next step without waiting for witness orchestration.

## Problem

Currently, when a polecat completes a molecule step:
1. Polecat sends POLECAT_DONE to witness
2. Witness (in patrol cycle) eventually reads mail
3. Witness spawns next step
4. **Minutes of latency possible**

Polecats also forget to close beads steps (using internal TodoWrite instead), breaking the activity feed.

## Solution

`gt mol step done <step-id>` handles everything:

1. Close the beads step (`bd close <step-id>`)
2. Extract molecule ID from step (bd-mol-xga.1 → bd-mol-xga)
3. Find next ready step (dependency-aware)
4. If next step exists:
   - Update hook file to point to next step
   - Write handoff context
   - tmux respawn-pane (fresh claude session)
5. If molecule complete:
   - Clear hook
   - Send POLECAT_DONE to witness
   - Exit session

## Key Insight

Step-to-step transitions are **mechanical**, not **cognitive**. No AI needed in the critical path. Pure Go automation.

## Related Commands

- `gt mol next <mol-id>` - Show next ready step(s)
- `gt mol progress <mol-id>` - Already exists

## Polecat Protocol Update

```markdown
When your hook contains a molecule step:
1. Read the step: `bd show <step-id>`
2. Execute the work described
3. When complete: `gt mol step done <step-id>`

That is it. Do NOT manually close steps. Do NOT work multiple steps.
```

## Benefits

- **Instant step transitions** (~5-10s vs minutes)
- **Activity feed works** (steps closed as completed)
- **Witness freed up** (safety net only, not critical path)
- **Fresh context per step** (better attention, no accumulated confusion)


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

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

Variables:
- gt-u2vg - The source issue ID being worked on


Doctor framework: Check interface, Result types, Report

Framework for gt doctor health checks.

## Check Interface

```go
type Check interface {
    Name() string
    Description() string
    Run(ctx *CheckContext) *CheckResult
    Fix(ctx *CheckContext) error  // optional auto-fix
    CanFix() bool
}

type CheckContext struct {
    TownRoot string
    RigName  string  // empty for town-level checks
    Verbose  bool
}

type CheckResult struct {
    Status  CheckStatus
    Message string
    Details []string  // additional info
    FixHint string    // suggestion if not auto-fixable
}

type CheckStatus int
const (
    StatusOK CheckStatus = iota
    StatusWarning
    StatusError
)
```

## Report

```go
type Report struct {
    Timestamp time.Time
    Checks    []CheckResult
    Summary   ReportSummary
}

type ReportSummary struct {
    Total    int
    OK       int
    Warnings int
    Errors   int
}

func (r *Report) Print(w io.Writer, verbose bool)
```

## Doctor Runner

```go
type Doctor struct {
    checks []Check
}

func NewDoctor() *Doctor
func (d *Doctor) Register(check Check)
func (d *Doctor) Run(ctx *CheckContext) *Report
func (d *Doctor) Fix(ctx *CheckContext) *Report  // run with auto-fix
```

## Built-in Checks

Town-level (gt-f9x.5):
- ConfigExists, ConfigValid
- StateExists, StateValid
- MayorMailboxExists
- RigsRegistryValid

Rig-level (gt-f9x.6):
- RigCloneExists
- GitExcludeConfigured
- WitnessExists, RefineryExists
- PolecatClonesValid


Digest: mol-deacon-patrol

Patrol 3: All clear


Swarm remaining gt-8tmz P3/P4 issues

## Swarm Plan for Molecule Algebra Completion

Encapsulates the remaining swarmable work from gt-8tmz (Molecule Algebra epic).

### Swarmable Issues (6 total)

**Batch 1 - Parallel (3 polecats):**
- gt-8tmz.10: Rename Engineer in Box to Shiny (simple rename)
- gt-8tmz.36: Validate expanded step IDs are unique (validation)
- gt-8tmz.31: Formula validation specification (docs)

**Batch 2 - Sequential (1 polecat):**
- gt-8tmz.34: Expansion var overrides → gt-8tmz.35: Inline step expansion
  (dependency chain - .35 depends on .34)

**Batch 3 - Solo (1 polecat):**
- gt-8tmz.30: Proto debugging and inspection tools (add --graph)

### Hold for Human (7 issues - need design decisions)
- gt-8tmz.19: Meta-formulas (schema design)
- gt-8tmz.20: Org inheritance (policy structure)
- gt-8tmz.21: Conditional aspects (when clause syntax)
- gt-8tmz.22: Review dimensions as aspects (refactor)
- gt-8tmz.28: Error handling policy
- gt-8tmz.29: Versioning strategy
- gt-8tmz.37: Nested expansion recursion

### Code Location
All work is in beads repo: /Users/stevey/gt/beads/crew/emma
- internal/formula/*.go
- cmd/bd/cook.go

### Execution
Hand to Witness for polecat dispatch, or execute manually with polecats.


test


burn-or-loop

Squash wisp and decide: loop or cycle session.

If context low: spawn new wisp and loop
If context high: handoff and request cycle

Needs: generate-summary


bd close --continue: auto-advance to next molecule step

Add --continue flag to bd close for seamless molecule step transitions.

## Usage

bd close <step-id> --continue [--no-auto]

## Behavior

1. Closes the specified step
2. Finds next ready step in same molecule (sibling/child)
3. By default, marks it in_progress (--no-auto to skip)
4. Outputs the transition

## Output

[checkmark] Closed gt-abc.3: Implement feature

Next ready in molecule:
  gt-abc.4: Write tests

[arrow] Marked in_progress (use --no-auto to skip)

## If no next step

[checkmark] Closed gt-abc.6: Exit decision

Molecule gt-abc complete! All steps closed.
Consider: bd mol squash gt-abc --summary '...'

## Key behaviors
- Detects parent molecule from closed step
- Finds next unblocked sibling
- Auto-claims by default (propulsion principle)
- Graceful handling when molecule is complete

## Beads feature
This is a bd command - needs implementation in beads repo.


Prompt templates: role contexts, nudge messages

Prompt templates for role contexts and messages.

## Template Types

### Role CLAUDE.md Templates

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

### Message Templates

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

## Implementation

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

type Templates struct {
    fs embed.FS
}

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

## Template Data

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

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

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

## Template Location

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

## Usage

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


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


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


Digest: mol-deacon-patrol

Patrol 10: OK


gt spawn beads sync warning is misleading for redirect-based polecats

## Problem

When spawning a polecat, gt spawn shows a warning:
```
Warning: beads sync: exit status 1
```

This is misleading because polecats using the redirect architecture (`.beads/redirect`) share the canonical database at `mayor/rig/.beads/beads.db`. The 'stale beads' indicated by the warning is just git branch divergence (main vs beads-sync), not actual data staleness.

## Expected Behavior

gt spawn should either:
1. Skip the beads sync check for polecats using redirects (they share the canonical DB)
2. Or provide a clearer message like 'beads redirect active, using shared database'

## Reproduction

```bash
gt spawn --issue gt-xxx --rig gastown --create
# Shows 'Warning: beads sync: exit status 1' even though beads are current
```

## Root Cause

spawn.go calls beads sync and treats any non-zero exit as a warning. But with redirects, the polecat doesn't need its own beads - it uses the canonical source via the redirect chain:
```
polecat/.beads/redirect -> ../../.beads -> gastown/.beads/redirect -> mayor/rig/.beads
```

## Fix Options

1. Check for .beads/redirect before calling sync
2. Have bd sync return 0 when redirect is present
3. Suppress the warning in spawn when redirect exists


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Test Polecat Arm

Test child for bonding pattern


Digest: mol-deacon-patrol

Patrol 20: All healthy, handoff triggered


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


mol-deacon-patrol


Test Patrol for Bonding

Parent issue for mol bond CLI test


Immediate daemon notification on lifecycle request

When gt handoff sends a lifecycle request to the daemon (via bd mail send deacon/), the daemon only discovers it on its next heartbeat poll (every 5 min). Workers wait unnecessarily for retirement.

## Current Behavior
1. Worker runs gt handoff
2. Lifecycle mail sent to deacon/ via beads
3. Worker blocks waiting for retirement
4. Daemon heartbeat runs (up to 5 min later)
5. Daemon processes lifecycle request and kills session

## Expected Behavior
Lifecycle requests should be processed immediately, not on poll interval.

## Proposed Solutions

### Option A: SIGUSR1 Signal (simplest)
1. Add SIGUSR1 handler in daemon that calls ProcessLifecycleRequests()
2. gt handoff reads daemon.pid and sends SIGUSR1 after mail send

### Option B: Unix Socket
1. Daemon listens on ~/gt/daemon/lifecycle.sock
2. gt handoff connects and sends 'process' message

### Option C: Watchfile + fsnotify
1. gt handoff touches ~/gt/daemon/lifecycle.trigger
2. Daemon uses fsnotify to detect and process

Recommend Option A for simplicity.

## Affected Files
- internal/daemon/daemon.go - add signal handler
- internal/cmd/handoff.go - send signal after mail


Digest: mol-deacon-patrol

Patrol 20: all healthy, handoff threshold reached


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol #12


Merge: gt-99a

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


Rollback support: gt mq revert for problematic merges

Implement 'gt mq revert <mr-id>' for rolling back merges.

Actions:
1. Find merge commit from closed MR
2. Create revert commit: git revert <merge-commit>
3. Push revert to target branch
4. Create 'reverted' MR tracking the revert
5. Optionally reopen source issue

Options:
- --reason REASON: required explanation
- --reopen-issue: reopen the source work item

Track revert in MR metadata for audit trail.

Reference: docs/merge-queue-design.md#open-questions


Digest: mol-deacon-patrol

Patrol 10: All services healthy


Digest: mol-deacon-patrol

Patrol 4: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol 16: All agents healthy


Digest: mol-deacon-patrol

Patrol 10: clear


Digest: mol-deacon-patrol

Patrol 9: All healthy


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

P18: stable


Remove schedule/phase terminology from code

Temporal/schedule language in identifiers is an anti-pattern.

## Found Issues

### beads repo
- `examples/multi-phase-development/` directory
  - Rename to `examples/dependency-sequenced-work/` or similar

### gastown repo
- `internal/cmd/start.go` lines 178-195
  - Uses "Phase 1:", "Phase 2:", etc. in printf output
  - Change to descriptive names: "Interrupting agents...", "Requesting handoff...", etc.

- `internal/swarm/landing.go` lines ~50-70
  - Comments say "// Phase 1: Stop all polecat sessions"
  - Change to "// Step: Stop all polecat sessions" or just remove phase labels

## Why This Matters

Phase/version language in names:
1. Implies a fixed schedule (antithetical to dependency-driven work)
2. Creates confusion with molecule "phases" (solid/liquid/gas)
3. Encourages temporal thinking that leads to backwards dependencies

## What To Keep

- Molecule phase terminology (pour/wisp/proto) - this is chemistry, not scheduling
- Version fields inside files (version: 1) - this is semantic versioning


Digest: mol-deacon-patrol

Patrol 2: all healthy, no callbacks


Aggregate arm results

Collect outcomes from all polecat inspection arms.

This is a **fanout gate** - it cannot proceed until ALL dynamically-bonded
polecat arms have completed their inspection cycles.

Once all arms complete, collect their outcomes:
- Actions taken per polecat (nudge, kill, escalate, none)
- Updated nudge counts
- Any errors or issues discovered

Build the consolidated state for save-state.


Selection operators: glob, filter, children

Implement selection operators for targeting:
- step(id) - specific step
- glob(pattern) - pattern match (*.implement)
- filter(predicate) - status/output predicates
- children(step), descendants(step) - tree traversal

Used by advice, expansion, and aspects for targeting.


health-scan

Ping Witnesses and Refineries. Run gt status --health. Remediate if down.


Bug: bd update --parent doesn't persist

The --parent flag on bd update reports success but doesn't persist the parent field.

**Confirmed behavior:**
```bash
bd update gt-9kp3t --parent=gt-d0jqp --no-daemon -v
# Output: ✓ Updated issue: gt-9kp3t

bd show gt-9kp3t --json | jq '.[0].parent'
# Returns: null

grep gt-9kp3t .beads/issues.jsonl | head -1 | jq '.parent'
# Returns: null (field not present)
```

**Root cause hypothesis:**
The update handler processes the --parent flag but either:
1. Doesn't write it to the Issue struct
2. Doesn't include it in the JSONL export
3. The field name doesn't match what export expects

**Files to check:**
- cmd/bd/show.go:638-640 (flag handling)
- cmd/bd/show.go:810-814 (reparenting logic)
- internal/rpc/server_issues_epics.go (RPC handler)
- internal/rpc/protocol.go (UpdateArgs.Parent field)

Related: bd-cj2e (the original feature implementation)


Digest: mol-deacon-patrol

Patrol 16


Pillar 3: Polecat Lifecycle

Session-per-step model with automated recycle/nuke.

Key deliverables:
- gt polecat recycle <name> - kill session, preserve sandbox
- gt polecat nuke <name> - kill everything
- Witness calls recycle between molecule steps
- Refinery calls nuke after merge

Subsumes existing work:
- gt-budeb: Witness auto-nuke polecats after merge
- gt-1dbcp: Polecat auto-start nudge fix

Reference: ~/gt/docs/liftoff-plan.md

Parent: gt-oki8p


Digest: mol-deacon-patrol

Patrol 17: All healthy


Digest: mol-deacon-patrol

Patrol 3: all clear


Document Rig/Cook/Run lifecycle

The rig-cook-run.md spec is written. Propagate terminology to all relevant docs: - molecule-algebra.md (done) - molecular-chemistry.md (done) - vision.md (done) - propulsion-principle.md - sling-design.md - Any agent templates that reference cooking/instantiation


Digest: mol-deacon-patrol

Patrol 13


Refinery background daemon mode

Refinery currently only works in foreground mode. Background daemon is stubbed.

## Current State
manager.go line 128-129:
```go
// Background mode: spawn a new process
// For MVP, we just mark as running - actual daemon implementation in gt-ov2
return nil
```

## Requirements

### 1. Background Process Spawning
```go
func (m *Manager) Start(foreground bool) error {
    if !foreground {
        // Spawn gt refinery start --foreground as subprocess
        cmd := exec.Command(os.Args[0], "refinery", "start", m.rig.Name, "--foreground")
        cmd.Start()  // Don't wait
        // Record PID
    }
}
```

### 2. PID File Management
- Write PID to .gastown/refinery.pid
- Check PID validity on status
- Clean up stale PID files

### 3. Log Output
- Redirect stdout/stderr to .gastown/refinery.log
- Log rotation (optional for MVP)

### 4. Graceful Shutdown
- Handle SIGTERM/SIGINT
- Complete current merge before exit
- Update state to stopped

### 5. Health Check
- Process existence check via kill -0
- Optional: heartbeat file with timestamp

## Files to Modify
- internal/refinery/manager.go: Start(), Status(), process spawning

## Acceptance Criteria
- [ ] gt refinery start <rig> spawns background process
- [ ] gt refinery status shows running with PID
- [ ] gt refinery stop sends SIGTERM and waits
- [ ] Logs written to .gastown/refinery.log
- [ ] Survives terminal close


Merge: gt-odvf

branch: polecat/slit
target: main
source_issue: gt-odvf
rig: gastown


Digest: mol-deacon-patrol

Patrol 17: 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-oh90
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Add agent abstraction layer to support non-Claude agents

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

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

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


Proto marketplace: shareable molecule templates

Enable sharing protos between Gas Town installations.

## Vision

A public registry of protos that users can pull and use:

```bash
gt proto search "code review"
gt proto install gastown/code-review
gt sling code-review gastown/Toast --wisp
```

## Registry Design

### Local Catalog
`~/gt/molecules/` - user-defined and installed protos

### Remote Registry
`registry.gastown.dev/protos/` (future)
- Browse online catalog
- Version-controlled protos
- Rating/reviews
- Usage statistics

## Proto Package Format

```
gastown-code-review-1.0.0/
├── PROTO.md          # Main proto definition
├── README.md         # Usage documentation
├── LICENSE           # Usage terms
└── plugins/          # For pluggable molecules
    ├── security/
    └── performance/
```

## Commands

```bash
gt proto list              # Show installed protos
gt proto search <query>    # Search registry
gt proto install <name>    # Install from registry
gt proto publish <path>    # Publish to registry
gt proto update            # Update all installed
```

## For Now

Start with local catalog. Marketplace is future phase.
Ensure proto format is registry-compatible from the start.


gt sling --on flag for wisp scaffolding

Add --on flag to gt sling for applying forms to existing work:
  gt sling shiny gastown/Toast --on gt-abc123

When --on is specified, implies --wisp (scaffolding existing work).
The form shapes execution of the target bead.


Digest: mol-deacon-patrol

Patrol 6: Nominal


gt mq submit: create MR from current branch

Implement 'gt mq submit' command that creates a merge-request bead.

Auto-detection logic:
1. Branch: current git branch
2. Issue: parse from branch name (polecat/Nux/gt-xyz → gt-xyz)
3. Target: main (or integration branch if --epic specified)
4. Worker: parse from branch name
5. Rig: current rig

Options:
- --branch BRANCH: explicit source branch
- --issue ISSUE: explicit source issue
- --epic EPIC: target integration/EPIC instead of main
- --priority P: override priority (default: inherit from source issue)

Creates merge-request bead and prints MR ID.

Reference: docs/merge-queue-design.md#creating-merge-requests


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol 7: All healthy


Load context

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

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


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


mol-deacon-patrol

Mayor's daemon patrol loop.

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


mol-deacon-patrol


Digest: mol-deacon-patrol

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


gt park command for parking molecules on external deps

Add `gt park` command for when polecat hits external dependency:

```bash
gt park --step=gt-mol.3 --waiting="beads:mol-run-assignee"
```

This command:
1. Adds blocked_by: external:beads:mol-run-assignee to the step
2. Clears assignee on the step
3. Clears assignee on molecule root
4. Sends handoff mail to self with context
5. Shuts down polecat session

The molecule enters "parked" state (derived: in_progress + no assignee + blocked step).

Part of cross-project dependency system.
See: docs/cross-project-deps.md

Depends on Beads: bd-om4a (external: blocked_by support)


Digest: mol-deacon-patrol

Patrol 3: All witnesses/refineries healthy, no work


Remove polecat state derivation from issue status

**File:** polecat/manager.go (lines 556-599)

**Current behavior:**
- Switch on issue.Status to derive polecat state
- Go decides: open/in_progress → Working, closed → Done

**Fix:**
- Polecat state comes from polecat, not inferred by Go
- Polecat signals state via mail or explicit field
- Or: remove state derivation entirely, just report issue status

**Lines to refactor:**
- manager.go:576-588 (switch statement)

**Priority:** P2 - less critical than daemon/heartbeat logic


Digest: mol-deacon-patrol

Patrol 9


gt spawn/crew setup should create .beads/redirect for worktrees

Crew clones and polecats need a .beads/redirect file pointing to the shared beads database (../../mayor/rig/.beads). Currently:

- redirect files can get deleted by git clean
- not auto-created during gt spawn or worktree setup
- missing redirects cause 'no beads database found' errors

Found missing in: gastown/joe, beads/zoey (after git clean)

Fix options:
1. gt spawn creates redirect during worktree setup
2. gt prime regenerates missing redirects
3. bd commands auto-detect worktree and find shared beads

This should be standard Gas Town rig configuration.


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


Split PGT/GGT harness or migrate to GGT-only

Current ~/ai harness is shared by PGT and GGT with confusing overlap. Options:
1. Keep separate (document the coexistence)
2. Migrate fully to GGT structure
3. Create separate harnesses

This affects the beads redirect, Mayor home location, and rig structure.


MR: gt-svi.1 (polecat/Furiosa)

branch: polecat/Furiosa
target: main
source_issue: gt-svi.1


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

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


Digest: mol-deacon-patrol

Patrol 15: all quiet


Role prompts have mismatched startup protocols

Different role prompts describe different startup protocols:

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

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


test sling pinned


Design: Mayor session cycling and handoff

Design for Mayor session cycling and structured handoff.

## Overview

Mayor coordinates across all rigs and runs for extended periods. Needs session cycling pattern with structured handoff notes.

## Key Elements

1. Session cycling recognition (when to cycle)
2. Handoff note format (structured state capture)
3. Handoff delivery (mail to self)
4. Fresh session startup (reading and resuming)

## Subtasks (implementation)

- gt-g2d: Mayor session cycling prompting
- gt-sye: Mayor startup protocol prompting
- gt-vci: Mayor handoff mail template
- gt-1le: town handoff command (optional, P2)

**Design complete.** Each subtask has full specification in its description.


Port Gas Town to Go

Complete rewrite of Gas Town in Go for improved performance and single-binary distribution.

## Goals
- Single installable binary (gt)
- All Python functionality ported
- Federation support built-in
- Improved performance

## Phases
1. Core infrastructure (config, workspace, git wrapper)
2. Rig & polecat management
3. Session & tmux operations
4. Mail system
5. CLI commands
6. TUI (optional)


Digest: mol-deacon-patrol

Patrol 4: Quiet


Work on gt-fix-bugs: Fix blocking infrastructure bugs. Se...

Work on gt-fix-bugs: Fix blocking infrastructure bugs. See issue for details. Run 'bd show gt-fix-bugs' to see the full issue.


bd create should support molecule type

gt molecule commands expect type=molecule but bd validates against bug|feature|task|epic|chore|merge-request only


gt mq list shows empty when MRs exist

The gt mq list command returns empty results even when merge requests exist in the queue.


Swarm learning: Witness needs automated context cycling

Furiosa hit 2% context during swarm work. Witness role needs automated detection of low context and should trigger session cycling before agents get stuck. Add to Witness responsibilities in prompts.md.


Day 2.3: Agent writes state on lifecycle events

Agents update their bead state:
- On startup: bd update gt-<role> --state=running
- On shutdown: bd update gt-<role> --state=stopped
- On stuck: bd update gt-<role> --state=stuck

State is self-reported, not inferred.

Parent: gt-d0jqp


Digest: mol-deacon-patrol

Patrol #6: Routine


Digest: mol-deacon-patrol


Document crew worker patrol integration

Document how mol-ready-work integrates with crew worker workflow. Cover: starting the patrol, patrol vs normal operation, backlog configuration, handoff mechanics, discovered work handling. Update CLAUDE.md with patrol section.


mol-deacon-patrol

Mayor's daemon patrol loop.

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


mol-deacon-patrol


gt mail: Cross-level routing is broken

**Problem:**
When Mayor (at ~/gt) sends mail to a rig worker (gastown/crew/max), the message lands in town-level beads (~/.beads/) but the recipient checks rig-level beads (crew/max/.beads/).

**Reproduction:**
```bash
cd ~/gt
gt mail send gastown/crew/max -s 'Test' -m 'body'
# Message goes to ~/gt/.beads/ with prefix hq-*

cd ~/gt/gastown/crew/max
gt mail inbox
# Does NOT see the message - it's looking in crew/max/.beads/
```

**Root cause:**
`findBeadsWorkDir()` walks up from CWD to find .beads. `Router.Send()` runs `bd create` in that directory. This means messages always go to the sender's beads, not the recipient's.

**Fix options:**
1. Route based on recipient address - if sending to rig/*, use that rig's .beads
2. Use a single shared beads database for all mail (simpler but less isolated)
3. Teach agents to check both levels (workaround, not fix)

**Related:**
- gt-ngu1: Pinned beads sorting (done but pointless if mail doesn't route)
- This blocks all cross-level mail functionality


Swarm package: Swarm, SwarmTask, SwarmState types

Define core swarm types.

## Types (in `internal/swarm/`)

```go
// SwarmState represents swarm lifecycle
type SwarmState string
const (
    SwarmCreated   SwarmState = "created"
    SwarmActive    SwarmState = "active"
    SwarmMerging   SwarmState = "merging"
    SwarmLanded    SwarmState = "landed"
    SwarmFailed    SwarmState = "failed"
    SwarmCancelled SwarmState = "cancelled"
)

// Swarm references a beads epic that tracks swarm work
type Swarm struct {
    ID          string      // matches beads epic ID
    RigName     string
    EpicID      string      // beads epic tracking this swarm
    BaseCommit  string      // git SHA all workers branch from
    Integration string      // integration branch name
    State       SwarmState
    CreatedAt   time.Time
    Workers     []string    // polecat names assigned
}

// SwarmTask represents a single task in the swarm (maps to beads issue)
type SwarmTask struct {
    IssueID   string  // beads issue ID
    Assignee  string  // polecat name
    Branch    string  // worker branch name
    State     string  // mirrors beads status
}
```

## Note

Swarm state is primarily stored IN beads. These types are in-memory representations for the SwarmManager to work with. No separate manifest.json files.


Review and audit all GGT beads

Thorough review of all filed beads in gastown GGT repo. Check for: consistency, completeness, correct dependencies, accurate descriptions, proper prioritization. Ensure beads are self-contained and dont rely on external docs.


gt crew status: Show workspace status

Implement 'gt crew status [<name>]' command:
- Show session state (running/stopped)
- Show git status (branch, uncommitted changes, unpushed)
- Show last commit info
- Show mail inbox status (unread count)
- If no name given, show all crew workers


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol 7: All healthy


Molecule CLI: bd molecule commands

Add molecule commands to bd:

## Commands

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

## gt spawn integration

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

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

## Output Examples

```
$ bd molecule show mol-abc

mol-abc: Engineer in a Box
Type: molecule

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

Instances: 3
```

```
$ bd molecule instances mol-abc

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


Witness: bond mol-polecat-arm when discovering polecat

When witness discovers a polecat during healthCheck(), bond a mol-polecat-arm child.

## Changes to witness/manager.go

In healthCheck() when iterating polecats:
1. Check if arm already exists for this polecat (arm-{name})
2. If not, call: gt mol bond mol-polecat-arm --parent=$PATROL_ID --ref=arm-{name} --var polecat_name={name} --var rig={rig}
3. Track arm issue ID in handoff state

## Arm Lifecycle

- Created when polecat first seen
- Updated as inspection happens (nudges, state changes)
- Closed when polecat cleaned up

## Deduplication

Check handoffState.WorkerStates[name].ArmID before creating.
Needs: gt-59zd.3


Digest: mol-deacon-patrol

Patrol 17: All healthy


Post-work discovery: AI analysis finds follow-on issues

AI analyzes completed work to discover: bugs, punted work, follow-on tasks.

**From VC**: Supervisor.AnalyzeResult() with iterative refinement. ~300 lines.

**Gas Town implementation**: Post-work hook in molecule:
```yaml
post_work:
  discover:
    - bugs
    - punted_items
    - follow_on_work
  file_as: beads
```

Polecat output gets analyzed by AI, discovered work becomes beads issues.

**Value**: Nothing gets forgotten. VC found ~25% more issues with refinement.

**Key**: Use semantic deduplication (gt-xxx) to avoid pollution.


Digest: mol-deacon-patrol

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


Integration test: agent waits for CI via gate

End-to-end test of the gate workflow.

## Test Scenario
1. Agent creates gate: bd gate create --await gh:run:123 --timeout 5m --notify beads/dave
2. Agent writes handoff and exits
3. Deacon patrol checks gate condition
4. (Mock) GitHub run completes
5. Deacon notifies waiter and closes gate
6. New agent session reads mail and resumes

## Test Requirements
- Mock GitHub API responses
- Test timeout path
- Test multiple waiters
- Verify mail notifications sent

## Moved from beads
Originally bd-rl5t. Tests Deacon patrol which is in gastown.


Design: Failure modes and recovery

Document failure modes and recovery strategies for Gas Town operations.

## Critical Failure Modes

### 1. Agent Crash Mid-Operation

**Scenario**: Polecat crashes while committing, Witness crashes while verifying

**Detection**:
- Session suddenly gone (tmux check fails)
- State shows 'working' but no session
- Heartbeat stops (for Witness)

**Recovery**:
- Doctor detects via ZombieSessionCheck
- Capture any recoverable state
- Reset agent state to 'idle'
- For Witness: auto-restart via supervisor or manual gt witness start

### 2. Git State Corruption

**Scenario**: Merge conflict, failed rebase, detached HEAD

**Detection**:
- Git commands fail
- Dirty state that won't commit
- Branch diverged from origin

**Recovery**:
- gt doctor reports git health issues
- Manual intervention recommended
- Severe cases: remove clone, re-clone

### 3. Beads Sync Conflict

**Scenario**: Two polecats modify same issue

**Detection**:
- bd sync fails with conflict
- Beads tombstone mechanism handles most cases

**Recovery**:
- Beads has last-write-wins semantics
- bd sync --force in extreme cases
- Issues may need manual dedup

### 4. Tmux Failure

**Scenario**: Tmux server crashes, socket issues

**Detection**:
- All sessions inaccessible
- "no server running" errors

**Recovery**:
- Kill any orphan processes
- tmux kill-server && tmux start-server
- All agent states reset to idle
- Re-spawn active work

### 5. Claude API Issues

**Scenario**: Rate limits, outages, context limits

**Detection**:
- Sessions hang or produce errors
- Repeated failure patterns

**Recovery**:
- Exponential backoff (handled by Claude Code)
- For context limits: session cycling (mail-to-self)
- For outages: wait and retry

### 6. Disk Full

**Scenario**: Clones, logs, or beads fill disk

**Detection**:
- Write operations fail
- git/bd commands error

**Recovery**:
- Clean up logs: rm ~/.gastown/logs/*
- Remove old polecat clones
- gt doctor --fix can clean some cruft

### 7. Network Failure

**Scenario**: Can't reach GitHub, API servers

**Detection**:
- git fetch/push fails
- Claude sessions hang

**Recovery**:
- Work continues locally
- Queue pushes for later
- Sync when connectivity restored

## Recovery Principles

1. **Fail safe**: Prefer stopping over corrupting
2. **State is recoverable**: Git and beads have recovery mechanisms
3. **Doctor heals**: gt doctor --fix handles common issues
4. **Emergency stop**: gt stop --all as last resort
5. **Human escalation**: Some failures need Overseer intervention

## Implementation

- Document each failure mode in architecture.md
- Ensure doctor checks cover detection
- Add recovery hints to error messages
- Log all failures for debugging


Test Polecat Arm

Test child for bonding pattern


CLI: spawn command

High-level command to spawn a polecat with work assignment.

## Command

```
gt spawn <rig>/<polecat> --issue <id>
gt spawn <rig> --issue <id>  # auto-select available polecat
gt spawn <rig>/<polecat> -m "Work on X"  # free-form task
```

## What It Does

1. Select or create polecat
2. Ensure polecat is in idle/active state
3. Assign the issue (update beads, set polecat state)
4. Start session (gt session start)
5. Inject initial context

## Options

- `--issue <id>`: Beads issue to assign
- `-m "message"`: Free-form work description
- `--create`: Create polecat if it does not exist
- `--no-start`: Assign work but do not start session

## Auto-Select Logic

If polecat not specified:
1. Look for idle polecats in rig
2. Prefer ones that worked on similar issues before
3. If none available, fail (or create if --create)

## Initial Context

Injects into session:
```
[SPAWN] You have been assigned: <issue-title>
Issue: <id>
Priority: <priority>

<description>

Work on this issue. Signal DONE when complete.
```

## Implementation

Orchestrates PolecatManager + SessionManager + Beads:
```go
func Spawn(rig, polecat, issue string, opts SpawnOptions) error
```


Town & Rig Management: install, doctor, federation

Reify the Gas Town installation as a first-class concept.

## Goals
- Installable: gt install [path] creates complete installation
- Diagnosable: gt doctor checks and fixes issues
- Federable: Clone town to VMs with central control

## Architecture Reference

See docs/architecture.md for full design, especially:
- Directory structure (Town Level / Rig Level sections)
- Configuration (town.json, rigs.json schemas)
- Key design decisions (visible config dir, decentralized agents)


Digest: mol-deacon-patrol

Patrol cycle 7: all nominal


Update templates with molecule navigation workflow

Update all agent templates to use new molecule navigation commands.

## Commands to integrate
- bd mol current: orientation after startup/handoff (bd-sal9)
- bd close --continue: seamless step transitions (bd-ieyy)

## Templates to update

### prompts/roles/polecat.md
- Add bd mol current to 'Finding Your Work' section
- Replace manual 3-command dance with bd close --continue
- Update 'Working Through Steps' section

### prompts/roles/crew.md
- Add molecule navigation to workflow section
- Show bd mol current for session startup

### prompts/roles/refinery.md
- Update patrol step transitions to use --continue

### prompts/roles/witness.md
- Update patrol step transitions to use --continue

### prompts/roles/deacon.md
- Update patrol step transitions to use --continue

## Key message
The Propulsion Principle: close a step, immediately get handed the next.
No friction, no forgetting, no 3-command dance.

## Blocked by (Beads features)
- bd-sal9: bd mol current
- bd-ieyy: bd close --continue

BLOCKED 2025-12-23 00:17: Waiting for beads features (bd mol current, bd close --continue) to be implemented. Notified mayor.


Phase 1: Slinging Handoff

# Phase 1: Slinging Handoff

The restart-and-resume loop. This is the fundamental propulsion mechanism.

## What It Does

```bash
gt sling gt-xxx
```

1. Creates a wisp on the agent's hook containing the bead
2. Sends handoff mail (optional context)
3. Triggers session restart (daemon SIGUSR1 or direct respawn)
4. Fresh Claude wakes up
5. SessionStart hook runs `gt prime`
6. Agent reads hook → finds the slung bead
7. Agent executes the work

## Why Wisp, Not Mol

The sling is ephemeral scaffolding. It says "run this bead" - nothing more.
Once the work is picked up, the wisp can be burned. No permanent record needed
for the handoff wrapper itself; the actual work is tracked in the bead.

## Implementation

### gt sling command

```go
// cmd: gt sling <bead-id> [-s subject] [-m message]
func sling(beadID string, subject, message string) {
    // 1. Create wisp on hook
    //    - Creates .beads-wisp/hook-<agent>.wisp.yaml
    //    - Contains: bead_id, slung_at, context

    // 2. Optional: send handoff mail
    //    - gt mail send <self> -s "🤝 HANDOFF: <subject>" -m "<message>"

    // 3. Trigger restart
    //    - For crew: just exit (human restarts)
    //    - For polecats: signal daemon (SIGUSR1)
    //    - For deacon: signal daemon (SIGUSR1)
}
```

### Hook Reading in gt prime

```go
// In gt prime, after loading context:
func checkHook(agent string) *SlungWork {
    wispPath := ".beads-wisp/hook-" + agent + ".wisp.yaml"
    if exists(wispPath) {
        return parseWisp(wispPath)
    }
    return nil
}
```

### Agent Response to Slung Work

When agent wakes and finds slung work:

1. Read the wisp: `hook-<agent>.wisp.yaml`
2. Get the bead ID
3. Show the bead: `bd show <bead-id>`
4. Begin working on it
5. Burn the wisp (it's been picked up

## Files Changed

-  - New command
-  - Wisp creation/reading
-  - Hook check on startup
- Role CLAUDE.md files - Instructions for hook processing

## Acceptance Criteria

- [ ]  creates wisp on hook
- [ ] Agent restart picks up the slung work
- [ ] Work begins automatically (no human nudge)
- [ ] Wisp is burned after pickup
EOF
)


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol: 2 completions (valkyrie gt-yd98 MQ, scrotus gt-mzal.1 boot proto). 8 polecats working.


Process witness mail

Process witness mail: lifecycle requests, help requests.

```bash
gt mail inbox
```

Handle by message type:
- **LIFECYCLE/Shutdown**: Queue for pre-kill verification
- **Blocked/Help**: Assess if resolvable or escalate
- **HANDOFF**: Load predecessor state
- **Work complete**: Verify issue closed, proceed to pre-kill

Record any pending actions for later steps.
Mark messages as processed when complete.


gt swarm: Not discovering tasks from epic dependents

gt swarm create/start shows '0 tasks loaded' even when epic has dependents.

Repro:
1. Create epic gt-hw6
2. Create tasks and add deps: bd dep add gt-xxx gt-hw6
3. gt swarm create gastown --epic gt-hw6 --worker Toast
4. Swarm shows 'Tasks: 0'

Expected: Swarm should discover tasks that depend on the epic.
Actual: Shows '(no tasks loaded)'


Digest: mol-deacon-patrol

Patrol 7


Digest: mol-deacon-patrol

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