Digest: mol-deacon-patrol

Patrol 2: Quick scan, all healthy, no work


bd mol publish: Push formula to GitHub repo

Publish a local formula to a GitHub repository.

Usage: bd mol publish <formula-name> <github-repo>

Should:
- Create or update GitHub repo with formula
- Add README.md from formula metadata
- Tag with version
- Set appropriate topics for discoverability


Digest: mol-deacon-patrol

Patrol 12: Quiet


Digest: mol-deacon-patrol

Patrol 17: all clear


Digest: mol-deacon-patrol

P20: stable - handoff triggered


Digest: mol-deacon-patrol

Patrol 2: Quick scan, no changes


Digest: mol-deacon-patrol

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


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

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

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


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

Patrol 18: All healthy


Digest: mol-deacon-patrol

Patrol 2: Routine, 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
```


Digest: mol-deacon-patrol

P19: stable


Implement meta-formula generator in parser

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

## Implementation

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

## API

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

## Edge Cases

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


Documentation overhaul: User Guide approach

## Problem

Current docs are:
1. **Grandiose** - Too much vision, belongs in ~/gt/docs (HOP), not here
2. **Verbose** - Need bullets/tables, not sections. Too many separate files.
3. **Bottom-up** - Written as we built. Users need top-down.

Gas Town is a simple agent orchestrator (4-10 → 20-30 agents). Not a manifesto.

## Target Structure

### 1. Features at a Glance
- Persistent agent identities with mail inboxes and "work hooks"
- Sling work to agents, pinned to their hook
- Universal Propulsion: If hook is pinned, RUN IT
- Hooks survive crash, shutdown, compaction, restart
- Self-sling for auto-restart workflows
- Pin individual beads or entire epics

### 2. Available Workflows
- tmux mode vs no-tmux (raw Claude Code)
- Full Gas Town vs partial (single roles)
- Modular and resilient - one role at a time

### 3. Cooking Formulas
- Molecules = chains of issues (railroad tracks)
- Formulas = step descriptions (atoms)
- Cook formulas → molecules → durable workflows
- Examples: release molecule, deacon patrol, polecat workflow, shiny

### 4. (Optional) MEOW Deep Dive
- Structured epics as chained work graphs
- Serial/parallel branches, gates, loops, algebra
- States of matter, polymorphic bond operators
- But users just need to cook formulas

## Deliverable

One README + maybe one or two supporting docs. Radically condensed.


Control flow: loop, gate, branch

Implement control flow operators for the molecule algebra.

## Core Operators

| Operator | Syntax | Purpose |
|----------|--------|---------|
| loop (fixed) | loop: { count: N, body: [steps] } | Fixed iteration |
| loop (conditional) | loop: { until: COND, max: N, body: [steps] } | Bounded conditional iteration |
| gate | gate: { before: step, condition: COND } | Wait for condition before proceeding |
| branch | branch: { from: step, steps: [a,b,c], join: step } | Parallel paths that rejoin |

Conditions evaluated mechanically (step status, output fields) per gt-8tmz.7.

## Design Review (2025-12-25)

Analyzed patrol patterns (witness, deacon, refinery) to verify these constructs
can express real Gas Town workflows. Key findings:

### Insight: Patrol Loop is OUTSIDE the Algebra

The daemon respawns patrols. Each formula describes ONE cycle. This means:
- Formulas don't need "infinite loop with burn-and-respawn"
- loop is only for **inner loops** (refinery's per-branch processing)
- "burn-or-loop" = complete cycle; daemon decides next action
- Context cycling is external, not algebraic

This significantly simplifies the algebra.

### Gap: for-each is Missing

The current proposal doesn't include for-each, but it's essential for patrol patterns:

| Pattern | Use Case |
|---------|----------|
| Witness survey-workers | For each polecat, bond an arm (parallel) |
| Refinery process-branch | For each branch in queue, run merge pipeline (sequential) |
| Deacon plugin-run | For each plugin where gate open, execute |

Proposed syntax:

    for-each:
      collection: "survey-workers.output.polecats"
      bond: mol-polecat-arm
      vars:
        polecat_name: "{item.name}"
      parallel: true

This overlaps with gt-8tmz.8 (runtime dynamic expansion). Decision needed:
- Include for-each here as control flow, OR
- Ensure gt-8tmz.8 covers these patterns adequately

### Gap: waits-for Gate Variant

The "fanout gate" pattern (aggregate waits for all dynamically-bonded children)
needs formalization:

    step: aggregate
    waits-for: children-of(survey-workers)

Currently exists in formulas as waits_for: "all-children" but not in the algebra spec.

### What This Covers

With these operators (plus for-each), patrols become fully expressible:

**Witness Patrol:**
- for-each polecat -> bond mol-polecat-arm (parallel)
- gate with waits-for: all-children for aggregation

**Refinery Patrol:**
- for-each branch -> process pipeline (sequential)
- gate for test verification before merge

**Deacon Patrol:**
- for-each plugin -> execute if gate open
- Simple sequence otherwise

### Scope Decision

**Option A**: Implement loop, gate, branch now. Track for-each and waits-for separately.

**Option B**: Expand scope to include for-each and waits-for formalization.

Recommendation: Option A - implement core constructs, create child issues for gaps.


Digest: mol-deacon-patrol

Patrol 13: Quiet


Clean dead sessions

Clean dead sessions.

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

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

Preserve audit trail. Only clean sessions confirmed dead.


Digest: mol-deacon-patrol

Patrol 3: All healthy, routine


Digest: mol-deacon-patrol

Patrol 2: all clear, systems healthy


Campaign: Large-Scale Work Graph Execution

A Campaign is a Molecule-wrapped Epic graph ready for orchestrated execution.

## Concept

Campaign = Molecule + Epics + Dependency Graph + Execution Strategy

Key properties:
1. **Work graph**: Linked epics with dependency edges (possibly from different authors)
2. **Combinators as glue**: >>, |, wrap define bridging/shaping between epics
3. **Molecule shell**: Provides execution state, persistence across sessions
4. **Witness-aware**: Can be parallelized across polecats on independent branches
5. **Single-rig scoped**: One rig executes it (spans sessions/polecats)

## The "Maximum Speed" Model

Witness becomes a scheduler that:
- Watches campaign progress
- Identifies ready nodes (all dependencies satisfied)
- Spawns/assigns polecats to ready nodes
- Respects parallelism constraints
- Handles failures (retry? skip? escalate?)

## Where Campaign Fits in MEOW

Campaign is the convergence point where work-tracking meets workflow-execution:
- An Epic-of-Epics (work dimension)
- A Molecule (workflow dimension)

## Open Questions

1. Campaign creation UX - manual wire vs declare intent?
2. Partial completion - can you commit progress and resume?
3. Distinct entity type or molecule with type="campaign"?
4. Cross-rig campaigns - can graph span multiple rigs?

## Related

- docs/formula_evolution.md - original discussion
- gt-8tmz - molecule algebra (foundation)


Digest: mol-deacon-patrol

Patrol #15: Stable


Digest: mol-deacon-patrol

Patrol 5: all clear


check-refinery

Ensure the refinery is alive and processing merge requests.

Needs: inbox-check


Merge: gt-qsvq

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


Auto-rebase on conflict: optional automatic rebase

Implement automatic rebase as conflict resolution option.

When on_conflict=auto_rebase and conflicts detected:
1. Attempt: git rebase <target> <source-branch>
2. If clean rebase: update source branch, continue merge
3. If conflicts in rebase: abort, fall back to assign_back
4. Force push rebased branch (worker's branch)

Requires:
- Worker branch must be force-pushable
- Config: on_conflict: auto_rebase

Risks:
- Force push can confuse workers
- Complex conflicts still need manual resolution

Reference: docs/merge-queue-design.md#conflict-resolution-strategies


Automatic spawn for ready work

Auto-spawn polecats for ready work:

When Witness has capacity (active_workers < max_workers):
1. Query bd ready for unblocked issues
2. Filter to rig-appropriate work (by prefix or epic)
3. For each ready issue up to capacity:
   - gt spawn --issue <id>
   - Track that we spawned for this issue

Configuration (in rig config.json):
- max_workers: 4 (default)
- spawn_delay: 5s between spawns
- auto_spawn: true/false

This enables 'fire and forget' swarming:
- Mayor creates epic with children
- Mayor tells Witness to work epic
- Witness spawns polecats automatically
- Witness cleans up as they complete


Day 3.4: Refinery processes MERGE_READY mail

Refinery patrol handles merge requests:
1. Check inbox for MERGE_READY messages
2. For each, verify branch exists
3. Run merge checks (tests, lint)
4. If passing, merge to main
5. Send MERGED signal back

Parent: gt-hwka3


Default crew name should be something better than 'main'

When creating a new rig, the default crew worker name is 'main'. This is confusing since:

1. 'main' is also the git branch name
2. It doesn't convey that this is the user's personal workspace
3. Crew names should feel more personal/distinct

Consider alternatives like:
- 'home' - the user's home base
- 'desk' - their personal desk
- 'joe/max/etc' - actual name-based defaults
- Let user pick during rig init


BUG: gt handoff --dry-run still sends mail

In handoff.go, the dry-run check happens AFTER sendHandoffMail() is called. This means --dry-run still sends mail.

**Location**: handoff.go L126-143

**Observed**: Testing with `gt handoff --dry-run -s 'Test' -m 'Message'` actually sent mail to mayor.

**Fix**: Move mail sending inside the non-dry-run block, or check dry-run first.

```go
// Current (buggy):
if handoffSubject \!= "" || handoffMessage \!= "" {
    sendHandoffMail(...)  // Executes even in dry-run\!
}
if handoffDryRun {        // Too late
    return nil
}

// Should be:
if handoffDryRun {
    // show what would happen
    return nil
}
// Then send mail
```


Digest: mol-deacon-patrol

Patrol 3: all quiet


Digest: mol-deacon-patrol

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


Design: Polecat Beads write access

Design for granting polecats direct beads write access.

## Background

With Beads v0.30.0 tombstone-based rearchitecture, we have solid multi-agent support. Reversing the original read-only decision.

## Benefits

- Simplifies architecture (no mail-based issue filing proxy)
- Empowers polecats to file discovered work
- Beads handles work-disavowal

## Complications

For OSS projects where you cannot commit to project .beads/, need per-rig beads repo configuration.

## Subtasks (implementation)

- gt-zx3: Per-rig beads configuration schema
- gt-e1y: Worker prompting updates for beads access
- gt-cjb: Witness proxy removal
- gt-082: Beads sync in decommission checklist

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


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

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

## Variables

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

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

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

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

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

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

Calculate: minutes since last activity.
Needs: capture

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

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

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

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

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

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

Record decision and rationale.
Needs: load-history

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

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

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

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

**none**: No action needed.

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

## Output

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

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


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

Patrol 20: final patrol before handoff


Track operational stats as entity/audit beads

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

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

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

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


gt sling to town roles should use Town beads

## Problem

When Mayor starts from ~/gt (town root), `gt mol status` couldn't find beads pinned in rig beads.

## Solution

Added cross-rig scanning for town-level roles (mayor, deacon):
1. First check local beads directory
2. If nothing found AND target is a town-level role, scan all registered rigs
3. Return first pinned bead found

This makes `gt mol status` work correctly regardless of where Mayor is when checking hook status.

## Tested

1. `gt sling gt-552hb mayor` from gastown/mayor/rig/ - pins in rig beads ✓
2. `gt mol status` from ~/gt - finds the pinned bead via cross-rig scan ✓


witness Handoff


MessagingConfig: Fix error message inconsistency in validation

Negative value errors don't wrap ErrMissingField while empty-list errors do. Should be consistent - either all wrap a sentinel or none do.


Formula versioning and migration strategy

Define how formula versions are managed:
- What does the version field mean? Semver? Integer?
- When a formula changes, what happens to existing protos?
- Do protos track their source formula version?
- Migration path: old proto + new formula = ?
- Backwards compatibility guarantees (if any)

Deferred: post-launch polish


Digest: mol-deacon-patrol

Patrol 9: Refineries healthy


Advice operators: before, after, around

Implement Lisp-style advice operators for molecules:
- before(target, step) - insert step before target
- after(target, step) - insert step after target
- around(target, wrapper) - wrap target with before/after

Support glob patterns for targeting (*.implement, shiny.*, etc).


Digest: mol-deacon-patrol

Patrol 20: All healthy, routine cycle complete


Merge: gt-unrd

branch: polecat/Ace
target: main
source_issue: gt-unrd
rig: gastown


Work on ga-ct2: Add MR workflow to polecat completion. Wh...

Work on ga-ct2: Add MR workflow to polecat completion. When polecat completes work, auto-create MR to integration branch. When done, submit MR (not PR) to integration branch for Refinery.


Digest: mol-deacon-patrol

Patrol 5: all quiet


Sling reports 'already pinned' but mol status shows empty hook

During swarm operations, gt sling reported beads were 'already pinned' but gt mol status showed nothing on the hook.

**Observed:**
```
$ gt sling bd-9btu beads/Nux
Error: bead bd-9btu is already pinned to gt-beads-nux

$ gt mol status beads/Nux
Nothing on hook - no work slung
```

**Expected:**
If a bead is pinned, mol status should show it. If mol status shows empty, sling should work.

**Workaround:**
Used --force flag to re-sling, which worked.

**Root cause hypothesis:**
Agent bead state may be stored in town beads but polecat's local view doesn't see it, or the pin record exists but session state is stale.


attached_args: Standardize warning output to use style.Warning

Unify warning message formatting across codebase.

## Files to modify
- internal/cmd/start.go
- internal/cmd/polecat.go
- internal/cmd/mail.go
- Any other files with inconsistent warning output

## Current inconsistency
```go
fmt.Printf("%s Warning: ...", style.Dim.Render("⚠"))
fmt.Printf("Warning: %s", ...)
fmt.Fprintf(os.Stderr, "warning: ...")
```

## Standard pattern
Create helper if needed:
```go
// In internal/style/style.go
func PrintWarning(format string, args ...interface{}) {
    msg := fmt.Sprintf(format, args...)
    fmt.Printf("%s %s\n", Warning.Render("⚠ Warning:"), msg)
}
```

## Acceptance criteria
- [ ] PrintWarning helper in style package
- [ ] All warning outputs use consistent format
- [ ] Warnings go to stdout (not stderr) for consistency
- [ ] grep -rn 'Warning:' internal/cmd/ shows consistent format
- [ ] go build ./... passes


Digest: mol-deacon-patrol

Patrol 17: All clear


Digest: mol-deacon-patrol

Patrol 20: all clear, handoff due


Digest: mol-deacon-patrol

Patrol 11: routine, all healthy


Digest: mol-deacon-patrol

Patrol cycle 6: routine


Digest: mol-deacon-patrol

Patrol 7: Quiet


Remove all hardcoded gastown dependencies from gt codebase

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

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

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

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


Digest: mol-deacon-patrol

Patrol 17: all clear


gt spawn should create fresh polecat worktree, never reuse

Currently gt spawn tries to reuse existing polecats, which causes:

1. Stale beads database
2. Stale code (behind main/integration)
3. Old inbox messages
4. Git history pollution

## Current Behavior

gt spawn:
1. Looks for idle polecat in pool
2. If found, reuses existing worktree
3. Assigns new issue

## Desired Behavior

gt spawn:
1. Always create FRESH polecat from current main/integration
2. Fresh worktree with clean beads
3. No reuse of old worktrees

## Name Pool Still Useful

Keep name pool for:
- Allocating themed names (mad-max, etc.)
- Tracking which names are in use

But worktrees should be created fresh each time.

## Implementation

In spawn.go, before starting work:
1. If worktree exists: remove it first
2. Create fresh worktree from integration branch
3. Sync beads from rig to polecat
4. Then proceed with work assignment

This ensures polecats always start with latest code and beads.


Extended addressing: Parse [machine:]rig/polecat

Extended addressing for cross-machine operations.

## Address Format

```
[machine:]rig/polecat
```

Examples:
- `wyvern/Toast` - Local machine, wyvern rig, Toast polecat
- `gcp-vm-1:wyvern/Toast` - Remote machine
- `wyvern/` - Broadcast to rig
- `gcp-vm-1:wyvern/` - Broadcast to remote rig

## Parser

```go
type Address struct {
    Machine  string  // empty = local
    Rig      string
    Polecat  string  // empty = broadcast
}

func ParseAddress(s string) (*Address, error)
func (a *Address) String() string
func (a *Address) IsLocal() bool
func (a *Address) IsBroadcast() bool
```

## Validation

```go
func (a *Address) Validate(registry *MachineRegistry) error
```
- Machine must exist in registry (if specified)
- Rig must exist on machine
- Polecat must exist (if specified)

## Usage

All CLI commands that take addresses use ParseAddress:
```go
// gt mail send gcp-vm-1:wyvern/Toast -s "Hello"
addr, _ := ParseAddress("gcp-vm-1:wyvern/Toast")
conn, _ := registry.Connection(addr.Machine)
// Use conn for operations
```

## Backward Compatibility

Existing `rig/polecat` addresses work unchanged (Machine defaults to local).


attached_args: Remove os.Exit calls from Cobra RunE handlers

Replace os.Exit() calls with proper error returns in Cobra commands.

## Files to modify
- internal/cmd/mail.go (lines 546, 554, 561, 808-812)
- Any other files with os.Exit in RunE

## Problem
Some RunE handlers call os.Exit() directly:
```go
RunE: func(cmd *cobra.Command, args []string) error {
    ...
    os.Exit(1)  // BAD: bypasses Cobra error handling
}
```

## Fix
Return errors instead:
```go
RunE: func(cmd *cobra.Command, args []string) error {
    ...
    return fmt.Errorf("not in workspace")
}
```

## Acceptance criteria
- [ ] No os.Exit calls inside RunE functions
- [ ] Errors returned with proper context
- [ ] grep -n 'os.Exit' internal/cmd/*.go shows no RunE matches
- [ ] go build ./... passes
- [ ] Commands still exit with correct codes


Pillar 2: Patrol Ignition

Witness and Refinery patrol loops fire reliably.

Key deliverables:
- Witness patrol reads agent beads for polecat state
- Witness sends MERGE_READY to refinery on completion
- Refinery processes MERGE_READY mail
- Both send completion signals

Subsumes existing work:
- gt-6qyt1: Refinery event-driven merge queue
- gt-qpwv4: Witness detect completion
- gt-dtw9u: Witness active monitoring

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

Parent: gt-oki8p


Digest: mol-deacon-patrol

Patrol 15: All healthy.


Digest: mol-deacon-patrol

Patrol 6: routine


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: All healthy, no messages


MQ events in gt feed

Wire MQ lifecycle events to gt feed display.

After 'Refinery emits activity events' is done:
- gt feed should show merge_started, merged, merge_failed events
- Format: timestamp, event type, MR details
- Color coding: green for merged, red for failed

Example output:
  19:45 MERGED gt-abc123 (polecat/nux → main)
  19:42 MERGE_STARTED gt-abc123
  19:40 MERGE_FAILED gt-xyz789 (conflict)


Digest: mol-deacon-patrol

Patrol complete: no inbox, no polecats, cleaned 3 stale locks, witnesses/refineries intentionally stopped


Digest: mol-deacon-patrol

Patrol 3: inbox clear, all healthy


Digest: mol-deacon-patrol

Patrol cycle 2: quick scan, no changes


Digest: mol-deacon-patrol

Patrol 4: 9 sessions healthy


Crew worker jack in gastown - human-managed persistent workspace.

role_type: crew
rig: gastown
agent_state: running
hook_bead: null
role_bead: gt-crew-role
cleanup_status: null


Phase 1: Core messaging primitives (@group, list:, queue:)

## Scope

Core messaging infrastructure that enables multi-recipient and work-queue patterns.

### Deliverables

1. **Config directory structure** - ~/gt/config/ with lists.json, queues.json
2. **@group dynamic resolution** - Filesystem scan for agent directories
   - @rig/gastown → scan gastown/ for agents
   - @town → scan all rigs
   - @witnesses, @crew/gastown, etc.
3. **list:name static lookup** - Fan-out to N copies (each recipient gets work item)
4. **queue:name with claim** - Shared storage, atomic claim via bd update --claim
5. **Fan-out at send time** - gt mail send handles expansion

### Key semantics
- @group and list: both fan out (N copies, N obligations)
- queue: shared copy, first-to-claim wins
- All resolve at send time, not receive time


Mayor handoff mail template

Add MAYOR_HANDOFF mail template to templates.py.

## Template Function

def mayor_handoff(
    active_swarms: List[SwarmStatus],
    rig_status: Dict[str, RigStatus],
    pending_escalations: List[Escalation],
    in_flight_decisions: List[Decision],
    recent_actions: List[str],
    delegated_work: List[DelegatedItem],
    user_requests: List[str],
    next_steps: List[str],
    warnings: Optional[str] = None,
    session_duration: Optional[str] = None,
) -> Message:
    metadata = {
        'template': 'MAYOR_HANDOFF',
        'timestamp': datetime.utcnow().isoformat(),
        'session_duration': session_duration,
        'active_swarm_count': len(active_swarms),
        'pending_escalation_count': len(pending_escalations),
    }
    # ... format sections ...
    return Message.create(
        sender='mayor/',
        recipient='mayor/',
        subject='Session Handoff',
        body=body,
        priority='high',
    )

## Metadata Fields

- template: MAYOR_HANDOFF
- timestamp: ISO format
- session_duration: Human readable
- active_swarm_count: Number of active swarms
- pending_escalation_count: Number of escalations

## Mail Priority

Use priority='high' to ensure handoff is seen on startup.


Digest: mol-deacon-patrol

Routine patrol, town stable


Merge: gt-j6s8

branch: polecat/dementus
target: main
source_issue: gt-j6s8
rig: gastown


CLI cleanup: Remove duplicate mol commands from gt

## Problem
gt mol has commands that duplicate bd mol functionality:
- `gt mol catalog` (duplicate of `bd formula list`)
- `gt mol show` (duplicate of `bd mol show`)
- `gt mol squash` (duplicate of `bd mol squash`)
- `gt mol burn` (duplicate of `bd mol burn`)
- `gt mol bond` (duplicate of `bd mol bond`)

## Principle
- **bd** = beads operations (issues, molecules, formulas)
- **gt** = agent operations (sessions, communication, work dispatch)

gt should delegate to bd for beads operations, not duplicate them.

## Proposed Changes
Keep gt mol commands that are agent-specific:
- `gt mol status` - what is on MY hook
- `gt mol attach/detach` - hook management
- `gt mol current` - what should I work on
- `gt mol progress` - my progress through workflow

Remove/delegate to bd:
- `gt mol catalog` → use `bd formula list`
- `gt mol show` → use `bd mol show`
- `gt mol squash` → use `bd mol squash`
- `gt mol burn` → use `bd mol burn`
- `gt mol bond` → use `bd mol bond`

## Alternative
Keep as thin wrappers that just call bd, for convenience.


gt doctor: detect tmux session anomalies (linked panes, etc.)

Add a tmux health check to gt doctor that detects:

1. **Linked panes between sessions** - The bug where gt-deacon and gt-mayor shared pane @283, causing heartbeat crosstalk
2. **Session naming anomalies** - Sessions that don't match expected patterns
3. **Orphaned panes** - Panes in gt-* sessions with no running process

Detection approach:
- List all gt-* sessions
- For each session, get window/pane IDs
- Check for duplicate pane IDs across different sessions
- If found, report which sessions are linked and suggest fix

Auto-fix: Could offer to kill and recreate the offending session.

Reference: gt-rt6g documented a case where this caused the daemon's Deacon heartbeats to appear in the Mayor's input, eating user prompts.


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.


Merge: gt-ci84

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


Digest: mol-deacon-patrol

Patrol 6: Quick cycle, all quiet


Fix TestHasPolecat test failure in internal/session

TestHasPolecat in internal/session/manager_test.go fails because it expects
specific polecats (Toast, Cheedo) to exist in the test environment.

Error:
```
manager_test.go:46: expected hasPolecat(Toast) = true
manager_test.go:49: expected hasPolecat(Cheedo) = true
```

Fix: Either create test fixtures or mock the filesystem check.


Create molecules catalog directory structure

Establish the proto catalog at ~/gt/molecules/.

## Structure

```
~/gt/molecules/
├── README.md           # Catalog overview
├── lifecycle/
│   ├── gastown-boot/
│   │   └── PROTO.md    # Proto definition in markdown
│   ├── rig-spinup/
│   ├── rig-spindown/
│   └── agent-restart/
├── patrol/
│   ├── deacon-patrol/
│   ├── witness-patrol/
│   └── refinery-patrol/
└── work/
    ├── polecat-work/
    ├── code-review/
    └── feature/
```

## PROTO.md Format

```markdown
---
type: lifecycle
parallel: [ensure-witnesses, ensure-refineries]
ephemeral: true
---

# mol-gastown-boot

Town bootstrap molecule.

## Step: ensure-daemon
...
```

## Catalog Loading

`gt sling gastown-boot` should find the proto by:
1. Check beads for existing proto issue
2. If not found, scan ~/gt/molecules/lifecycle/gastown-boot/
3. Auto-create proto issue from PROTO.md

This enables file-based proto development with beads tracking.


Test Patrol Parent

Test parent for Christmas Ornament pattern


Day 2.2: Remove PID/tmux state inference

Remove ZFC violations where Go infers state from signals:
- No more PID file checks
- No more tmux session parsing
- No more branch pattern analysis

Daemon becomes pure transport layer.

Reference: ~/gt/docs/zfc-violations-audit.md

Parent: gt-d0jqp

Removed PID/tmux state inference from refinery Status(), witness Status(), daemon ensureDeaconRunning(), and daemon pokeDeacon(). Daemon now trusts agent bead state per ZFC. Removed 78 lines of inference code.


Digest: mol-deacon-patrol

Patrol 2: all agents healthy, no issues


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


gt done: Command doesn't exist but documented in polecat CLAUDE.md

The polecat CLAUDE.md documents 'gt done' as the command to signal work is ready for merge queue, but running it gives 'unknown command'. Either implement the command or update the documentation.


Digest: mol-deacon-patrol

Patrol 3: all healthy, mayor running, witnesses running


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


Refactor formula transformation pipeline to shared helper

The formula transformation pipeline (control flow, advice, expansions, aspects) is duplicated between cook.go and mol_bond.go. Should be extracted to a shared function in the formula package.

Current duplication in:
- cmd/bd/cook.go:96-136
- cmd/bd/mol_bond.go:598-633

Suggested approach:
- Add formula.Transform(resolved *Formula, parser *Parser) (*Formula, error)
- Handles all transformation steps in order
- Both cook.go and mol_bond.go call this single function


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

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


Digest: mol-deacon-patrol

Patrol 19: nominal


Unified Beads Namespace - prefix-based routing across town

Vision: Run bd commands from anywhere in town, with prefix-based routing.

Current state:
- Town beads at ~/gt/.beads/ with hq-* prefix
- Rig beads at ~/gt/<rig>/mayor/rig/.beads/ with rig-specific prefixes (gt-, bd-, wy-, etc.)
- Redirects allow agents to use specific beads location
- No automatic prefix-based routing

Desired state:
- bd show gt-xyz from ANYWHERE in town → routes to gastown beads
- bd show hq-abc from ANYWHERE in town → routes to town beads
- bd show wy-def from ANYWHERE in town → routes to wyvern beads
- Prefix determines beads location automatically

Implementation options:
1. Registry file at town root mapping prefix → beads location
2. bd wrapper/hook that reads prefix and routes
3. Unified store with namespace prefixes (more invasive)

Related work:
- gt-0pdhj: Remove hardcoded gastown dependencies
- Template fixes needed for deacon, witness, refinery CLAUDE.md


Digest: mol-deacon-patrol

Patrol: dave handoff (vision docs, 7 design gaps filed), furiosa tracer bullet on gt-oiv0, all agents up


Create mol-install-go-binary molecule

Create a single-step molecule for building and installing the gt binary.

## Molecule Definition
\`\`\`markdown
## Molecule: install-go-binary
Single step to rebuild and install the gt binary after code changes.

## Step: install
Build and install the gt binary locally.

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

Verify the installed binary is updated:
\`\`\`
which gt
gt --version  # if we have version command
\`\`\`
\`\`\`

## Implementation
1. Add to builtin_molecules.go
2. Update SeedBuiltinMolecules to include it
3. Run gt molecule seed

## Acceptance
- [ ] mol-install-go-binary exists in beads
- [ ] Can be instantiated standalone
- [ ] Can be included by other molecules


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

Patrol 14: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol 15: all healthy


Delete .runtime/*.json observable state

Remove JSON files that tracked observable state (now in beads/activity stream).

Files to delete or minimize:
- .runtime/refinery.json - remove stats (keep minimal process state if needed)
- .runtime/witness.json - remove stats
- .runtime/swarms.json - delete entirely (gt-kc7yj moves to beads)

Prerequisite: All events flowing through activity stream, swarms in beads.

This is the cleanup step after observability is working.


Digest: mol-deacon-patrol

Patrol 2: All healthy, routine


Refactor: Extract common manager creation boilerplate

Five nearly identical functions exist for creating managers:
- getPolecatManager (polecat.go:241)
- getSessionManager (session.go:183)
- getCrewManager (crew_helpers.go:44)
- getRefineryManager (refinery.go:116)
- getWitnessManager (witness.go:102)

All follow the same pattern: find workspace, load config, get rig, create manager. Should extract to a common helper that takes a factory function.


Create session name helper functions in internal/session

attached_args: Session name helper functions

Create helper functions for consistent session name construction.

## Files to modify
- internal/session/names.go (NEW)

## Implementation
Create new file with these functions:
```go
package session

import "fmt"

const Prefix = "gt-"

func MayorSessionName() string { return Prefix + "mayor" }
func DeaconSessionName() string { return Prefix + "deacon" }
func WitnessSessionName(rig string) string { return fmt.Sprintf("%s%s-witness", Prefix, rig) }
func RefinerySessionName(rig string) string { return fmt.Sprintf("%s%s-refinery", Prefix, rig) }
func CrewSessionName(rig, name string) string { return fmt.Sprintf("%s%s-crew-%s", Prefix, rig, name) }
func PolecatSessionName(rig, name string) string { return fmt.Sprintf("%s%s-%s", Prefix, rig, name) }
```

## Acceptance criteria
- [ ] New file internal/session/names.go created
- [ ] All 6 helper functions implemented
- [ ] Unit tests in internal/session/names_test.go
- [ ] go build ./... passes
- [ ] go test ./internal/session/... passes


Digest: mol-deacon-patrol

Patrol 18: all healthy, handled 1 handoff msg


Add event-triggered lifecycle wisps

Commands like `gt town start` should auto-trigger lifecycle wisps.

## Event → Wisp Mapping

| Command | Triggers Wisp |
|---------|---------------|
| gt town start | mol-gastown-boot |
| gt rig add <name> | mol-rig-spinup (param: rig=<name>) |
| gt rig remove <name> | mol-rig-spindown (param: rig=<name>) |
| gt daemon restart | mol-gastown-boot |

## Implementation

1. Command implementation checks for lifecycle proto
2. Auto-slings wisp to Mayor with --wisp flag
3. Mayor picks up via molecule attachment

## Alternative: Explicit Sling

Keep commands simple, require explicit:

```bash
gt town start        # Just starts sessions
gt sling gastown-boot mayor/ --wisp   # Bootstrap with verification
```

This is more transparent - user sees the sling happen.

## Recommendation

Start with explicit sling. Add auto-trigger later once pattern proven.
`gt town start --verified` could trigger the wisp.


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

Patrol 5: all healthy, 2 crews (dave, max) active


Digest: mol-deacon-patrol

Patrol 20: Final patrol, all healthy, handoff triggered


Merge: gt-7919

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


Digest: mol-deacon-patrol

P8: stable


gt polecat add: should handle existing branch gracefully

## Problem

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

## Current Behavior

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

## Expected Behavior

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

## Context

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


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.


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


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

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 20: all clear - handoff threshold reached


Wisp burn after pickup

Implement wisp cleanup after work is picked up.

## When to Burn

After agent has picked up slung work:
- Agent claims the issue (bd update --status=in_progress)
- Or agent explicitly acknowledges the handoff
- Wisp file is deleted

## Implementation Options

Option A: Agent burns manually
```bash
gt hook burn  # Deletes current hook wisp
```

Option B: Auto-burn on claim
- bd update detects theres a hook for this issue
- Burns the wisp automatically

Option C: Burn in prime (after display)
- Once shown to agent, delete the wisp
- Simple but might lose info if agent crashes before reading

## Recommendation

Use Option A (manual burn) for v0.1:
- Explicit is better than implicit
- Agent controls when theyre done with handoff
- Add auto-burn in v0.2

## Command

```bash
gt hook burn
# Deletes .beads-wisp/hook-<agent>.wisp.yaml
# Confirms: "Hook cleared"
```


Add logging for silently ignored errors

attached_args: Add logging for silently ignored errors

Add logging for silently ignored errors.

## Problem
Many places use `_ =` pattern to ignore errors without any logging, making debugging difficult.

## Files to modify
- internal/cmd/start.go (lines 167, 322-323, 429, 747-753, 886-888)
- internal/cmd/polecat.go (search for `_ =`)
- internal/session/manager.go (lines 140-154)
- internal/refinery/manager.go (line 399)
- internal/keepalive/keepalive.go (document as intentional)

## Implementation options

### Option A: Add comments explaining safety
```go
_ = m.saveState(ref) // Non-fatal: state will be recreated on next run
```

### Option B: Log warnings (preferred for important operations)
```go
if err := m.saveState(ref); err != nil {
    log.Printf("warning: failed to save state: %v", err)
}
```

## Guidelines
- Use logging for: state saves, config writes, cleanup operations
- Use comments for: truly benign operations (e.g., closing already closed file)
- keepalive is intentionally best-effort - add package-level comment

## Acceptance criteria
- [ ] All `_ =` in start.go have comment OR logging
- [ ] All `_ =` in session/manager.go have comment OR logging
- [ ] refinery/manager.go:399 has logging
- [ ] keepalive package has doc comment explaining best-effort design
- [ ] grep '`_ =`' shows all have justification
- [ ] go build ./... passes


Digest: mol-deacon-patrol

Patrol 7: Quick cycle, all quiet


Guardrail: Verify commits exist before closing polecat issues

## Updated Approach (ZFC)

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

## Correct Solution

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

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

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

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

## Why Not Code Guardrails

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

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

## Implementation

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


Refinery Engineer: Role prompting and CLAUDE.md

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


Liftoff implementation plan in Beads

## Context

Session on 2025-12-27 produced three key docs:
- `~/gt/docs/agent-as-bead.md` - Agents ARE beads (identity, hook slots, CV chain roots)
- `~/gt/docs/zfc-violations-audit.md` - Where Go infers instead of trusting agents
- `~/gt/docs/liftoff-plan.md` - 4.5 day plan to self-sustaining Gas Town

## Work Required

### Phase 1: Audit existing beads ✅
- Review all open beads in gt- prefix
- Close obsolete/stale issues
- Update any that need refinement
- Note which existing beads align with liftoff plan

### Phase 2: File new beads ✅
Translate liftoff-plan.md into beads with proper dependencies.

Three pillars:
1. **Pillar 1: Agent Identity** (gt-d0jqp) - schema, slot commands, migration
2. **Pillar 2: Patrol Ignition** (gt-hwka3) - witness/refinery formula wiring
3. **Pillar 3: Polecat Lifecycle** (gt-4a2qt) - recycle/nuke commands, session-per-step

### Phase 3: Review ✅
Human reviews the plan.

## Deliverable

A complete dependency graph in beads that can be:
1. Queried with `bd ready` to find available work
2. Slung to polecats in dependency order
3. Tracked to completion

## References

- ~/gt/docs/liftoff-plan.md - 4.5 day plan
- ~/gt/docs/agent-as-bead.md - Agent identity design
- ~/gt/docs/zfc-violations-audit.md - ZFC violations addressed


Molecule Phase Terminology Documentation

Document the three-phase molecule lifecycle with consistent terminology:

## The Phases (States of Matter)

| Phase | State | Nature |
|-------|-------|--------|
| **Proto** | Solid/Crystal | Frozen template, static definition in catalog |
| **Mol** | Liquid | Reified instance, malleable, tracked in git (durable) |
| **Wisp** | Gas | Evaporates after squash, ephemeral orchestration |

## Documentation Gaps Identified

### High Priority
1. Update vision.md Steam Engine metaphor to use proto/mol/wisp terminology
2. Add lifecycle diagram: Proto → bond → Mol or Wisp → squash → Digest
3. Document Go types for phases (ProtoMolecule, etc.)
4. Document .beads-ephemeral/ structure and purpose

### Medium Priority
5. Update CLAUDE.md files (polecat, witness, refinery) with molecule workflow
6. Document bd mol bond/squash/burn CLI API with examples
7. Add polecat guide: Executing molecules and generating summaries

### Low Priority
8. Add terminology glossary to architecture.md
9. Create troubleshooting playbook for stuck molecules
10. Add reference diagrams for state transitions

## Current State
- architecture.md has good molecule basics but uses inconsistent terminology
- vision.md has Steam Engine metaphor (proto=fuel, wisp=steam, digest=distillate)
- molecules.md has detailed reference but needs phase clarity
- builtin_molecules.go has 8 molecules but no phase documentation in code


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

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.


Refinery Patrol

Merge queue processor patrol loop with verification gates.


Crew agent beads never created (dead code in reportAgentState)

## Problem

In prime.go, reportAgentState is called for ALL roles including crew workers.
The function calls bd.UpdateAgentState for crew with ID like gt-crew-gastown-max.

But crew agent beads are NEVER created:
- Polecats: Created on spawn (polecat/manager.go:167)
- Infrastructure: Created by doctor/install (doctor/agent_beads_check.go)
- Crew: Nothing creates them

The error is silently ignored, so this doesn't break anything, but it's dead code.

## Found in commit

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

## Decision

**Create crew agent beads** on first gt prime if they don't exist.

Crew workers are human-managed but their state is still valuable for:
- Town-wide status dashboards
- Understanding who's working on what
- Consistent agent bead model across all agent types

## Implementation

In prime.go reportAgentState(), before calling UpdateAgentState:
1. Try to get the agent bead
2. If it doesn't exist, create it with CreateAgentBead
3. Then update state as normal


Extend auto-continue to polecats (not just crew)

gt prime currently only outputs AUTO-CONTINUE MODE for crew workers.
Polecats with attached work should also auto-continue.

## Current behavior
outputCrewAttachmentStatus() in prime.go:
- Only runs for RoleCrew
- Outputs '→ AUTO-CONTINUE MODE' when attached work detected

## Desired behavior
- Rename to outputAttachmentStatus() or similar
- Run for RoleCrew AND RolePolecat
- Same directive: if attachment exists, work immediately

## The Propulsion Principle
'If you find something on your hook, YOU RUN IT.'

This applies to ALL workers, not just crew.

## Implementation
1. Extend role check in outputCrewAttachmentStatus()
2. Adjust assignee detection for polecats vs crew
3. Test with both worker types


Create AgentIdentity type for session name parsing

attached_args: Create AgentIdentity type - depends on completed gt-atqr8

Create AgentIdentity type to parse and construct session names, replacing duplicated logic.

## Files to modify
- internal/session/identity.go (NEW)
- internal/cmd/sling.go (update to use new type)
- internal/cmd/handoff.go (update to use new type)

## Implementation
```go
type AgentIdentity struct {
    Role     string // mayor, deacon, witness, refinery, crew, polecat
    Rig      string // empty for mayor/deacon
    Name     string // crew/polecat name
}

func ParseSessionName(session string) (*AgentIdentity, error)
func (a *AgentIdentity) SessionName() string
func (a *AgentIdentity) Address() string // e.g., "gastown/crew/max"
```

## Acceptance criteria
- [ ] AgentIdentity type with Role, Rig, Name fields
- [ ] ParseSessionName handles all agent types (mayor, deacon, witness, refinery, crew, polecat)
- [ ] SessionName() reconstructs valid session name
- [ ] Address() returns mail-style address
- [ ] sling.go:sessionToAgentID replaced with ParseSessionName
- [ ] handoff.go:sessionToGTRole replaced with ParseSessionName
- [ ] Unit tests for all parsing cases
- [ ] go test ./... passes


Shutdown request handler

Handle polecat shutdown requests:

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

Depends on fixing gt-dsfi (handoff deadlock).


Direct test

Testing direct bd create


Digest: mol-deacon-patrol

Patrol #9


Update refinery to read local branches

Refinery manager needs to access polecat branches locally instead of fetching from origin.

## Changes
- internal/refinery/manager.go - remove origin fetch for MR branches
- internal/refinery/engineer.go - local branch access
- Remove DeleteRemoteBranch calls (branches are local now)
- Update merge workflow to work with local refs

## Key insight
All worktrees share the same .git - refinery can see polecat/nux branch directly.


Self-review

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

Fix any issues found before proceeding.


mol-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.


Work on ga-yp3: Polecat inbox system for reliable work as...

Work on ga-yp3: Polecat inbox system for reliable work assignment. This is P1 priority. See bd show ga-yp3 for full design spec.


Digest: mol-deacon-patrol

Patrol 5: nominal


Digest: mol-deacon-patrol

Patrol 18: clear


Witness events in gt feed

Wire witness patrol events to gt feed display.

After 'Witness emits activity events' is done:
- gt feed should show patrol activity
- Useful for debugging polecat issues

Example output:
  19:45 PATROL_COMPLETE gastown/witness (checked 3 polecats)
  19:44 POLECAT_NUDGED gastown/polecats/nux (idle 10m)
  19:40 ESCALATION mayor (polecat stuck)


Digest: mol-deacon-patrol

Patrol 5: All healthy.


Context cycling protocol

Document and verify gt handoff pattern for patrol agents. Ensure hook chain works: handoff mail sent, session respawns, SessionStart hook runs gt prime, work continues from pinned molecule.


Digest: mol-deacon-patrol

Patrol 12: All clear


Merge: gt-ay1r

branch: polecat/dementus
target: main
source_issue: gt-ay1r
rig: gastown


gt-gastown-polecat-ace

gt-gastown-polecat-ace

role_type: polecat
rig: gastown
agent_state: done
hook_bead: null
role_bead: gt-polecat-role
cleanup_status: has_stash


Digest: mol-deacon-patrol

Patrol 13: clear


Merge: furiosa-1766987668522

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


load-context

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

Read the assigned issue ({{issue}}) and understand the requirements.
Identify any blockers or missing information.


Digest: mol-deacon-patrol

Patrol 1: No callbacks, no gates, all agents healthy, cleaned 2 orphan processes + 1 stale lock


Digest: mol-deacon-patrol

Patrol 11: All green


Glass Cockpit: See WTF is happening

Glass cockpit - see what's happening across the system.

Phase 1 got the engine running. Phase 2 makes it observable.

**Pillars:**
- Pillar 4: Swarm-in-Beads (gt-kc7yj - already exists)
- Pillar 5: MQ Observability
- Pillar 6: Witness Observability
- Pillar 7: Unified Dashboard

**Success criteria:**
1. gt status shows per-rig queue depth and agent health
2. gt feed shows MQ and swarm lifecycle events
3. gt dashboard provides live system visibility
4. No .runtime/*.json files for observable state
5. Swarms fully tracked in beads

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


Digest: mol-deacon-patrol

Patrol 15: Quiet


Polecat template not found for non-gastown rigs

When adding a polecat to beads rig, warning shows:
  Warning: polecat template not found at /Users/stevey/gt/beads/mayor/rig/templates/polecat-CLAUDE.md

The template lookup should check the rig's template location, or fall back to a town-level default.


Add gt decommission command for clean swarm/worker shutdown

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


Digest: mol-deacon-patrol

Patrol 8: healthy


Design: Polecat lifecycle and patrol coordination

## Context

This design captures thinking from a deep session about the Gas Town propulsion system - how Deacon, Witness, Refinery, and Polecats coordinate to move work smoothly through the system.

## Core Insight: Session-Per-Step Model

Polecats do NOT complete complex molecules end-to-end. Instead:
- One polecat SESSION per molecule STEP
- Same sandbox (branch/worktree) persists across sessions
- Each step: spawn → work → close bead → recycle session
- Final step: spawn → work → close bead → signal complete → merge → nuke sandbox

## Two Cleanup Stages

| Stage | Trigger | Kills | Survives |
|-------|---------|-------|----------|
| Step cleanup | Step bead closed | Session | Branch, worktree, molecule |
| Molecule cleanup | Merged | Session, branch, worktree | Digest |

## Per-Rig Polecat Channel

Need a mailing list/queue per rig for session-lifecycle requests:
- "Recycle me" (from polecat)
- "Recycle worker X" (from witness/mayor)
- "Spawn for step Y" (from anyone)

First-come-first-served by patrolling agents. Anyone on patrol (Witness, Refinery, Crew, Mayor) can service requests.

## GUPP + Pinned Work = Completion

As long as:
1. Work is pinned to polecat identity (e.g., gastown/furiosa)
2. Sandbox persists (branch + worktree)
3. Someone keeps spawning polecat when it dies

→ The molecule WILL get finished. GUPP ensures wake-and-work.

## Daemon → Deacon Heartbeat

The daemon pings the deacon, keeping the cycle alive. Deacon peeks into rig-wide channels during patrol and can service lifecycle requests.

## Open Design Questions

### Q1: Spoon-Feeding Bin-Packing
Two dimensions of granularity trade-offs:
- How many logical steps per physical molecule step?
- How many molecule steps per polecat session?

Too few steps → context exhaustion, forgetting
Too many steps → overhead, fragmentation

Needs: Analysis of optimal granularity based on step complexity.

### Q2: Mechanical vs Agent-Driven Recycling
Caution from deacon murder spree bug: mechanical detection of "stuck" workers is fragile.

Prefer: Explicit "recycle me" requests serviced by patrol agents.

Question: When is mechanical intervention appropriate?

### Q3: Channel Implementation
Options:
- Mail-based (gt mail to rig/polecats)
- Beads-based (special issue type)
- State file (rig/polecat-queue.json)

Mail seems most consistent with Gas Town patterns.

### Q4: Who Spawns Next Step?
Current: gt sling spawns fresh polecat
Needed: Mechanism for "continue molecule on existing sandbox"

Maybe: gt sling --continue or witness detects pending step.

## Related Issues

- gt-dtw9u: Witness monitoring (enhance survey-workers)
- gt-qpwv4: Completion detection (check ready branches)
- gt-6qyt1: Refinery queue (process MERGE_READY)
- gt-budeb: Auto-nuke (handle MERGED signal)
- gt-5j3ia: Swarm aggregation (batch completion)
- gt-1dbcp: Polecat auto-start (SessionStart hook issue)

## Design Principles (from HOP/MEOW context)

1. **Discovery over tracking** - observe reality each cycle
2. **Mail as coordination primitive** - agents signal via mail
3. **ZFC** - Claude makes judgment calls, no hardcoded thresholds
4. **Redundant monitoring** - overlapping observation is resilience
5. **Wisps are ephemeral** - patrol molecules flow like water

## Next Steps

1. Finalize channel design (mail-based queue)
2. Enhance witness patrol formula with completion detection
3. Enhance refinery patrol with MERGED signaling
4. Implement step-level recycling
5. Design spoon-feeding granularity guidelines


Swarm beads naming convention and auto-filing

Beads naming convention for swarm lifecycle events.

## Bead IDs

- swarm-started:<swarm-id>     # Filed when swarm begins
- swarm-task-merged:<swarm-id>:<task-id>  # Filed per task merge
- swarm-landed:<swarm-id>      # Filed when merged to main
- swarm-failed:<swarm-id>      # Filed on unrecoverable failure

## swarm-started Bead

Filed by: Mayor/Refinery at swarm creation
Contains:
- Swarm title and description
- List of tasks (issue IDs)
- List of workers (polecat names)
- Base commit SHA

## swarm-task-merged Bead

Filed by: Refinery after each successful merge
Contains:
- Task issue ID and title
- Polecat name
- Merge commit SHA
- Test results summary

## swarm-landed Bead

Filed by: Refinery after landing to main
Contains:
- Final merge commit SHA
- Stats: tasks completed, time taken
- List of all merged task beads
- Integration branch name (now deleted)

## swarm-failed Bead

Filed by: Refinery on unrecoverable failure
Contains:
- Failure reason
- Tasks merged vs not merged
- Recovery guidance

## Why Beads (not just mail)

- Persistent, queryable, synced to git
- Other agents can check status without mail
- Creates audit trail
- Works when agents offline


Review: Refinery patrol template changes (gt-qz2l)

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


gt sling --force: return displaced work to ready pool

When slinging with --force to an agent with occupied hook, the displaced molecule should be returned to the ready pool rather than silently orphaned.

Current behavior:
- --force overwrites the hook attachment
- Previous work becomes orphaned (still assigned but not pinned)

Desired behavior:
1. Unpin the displaced molecule (clear assignee, set pinned=false)
2. Print warning in tool output: 'Warning: displaced gt-xxx back to ready pool'
3. Proceed with new sling

This ensures:
- No silent data loss
- Agent sees the warning and can act on it
- Human caller sees what happened
- Displaced work is discoverable via 'bd ready'

Implementation location: checkHookCollision() or the sling handlers themselves (after the --force check passes)


MR: gt-test (main)

branch: main
target: main
source_issue: gt-test


Merge: gt-ih0s

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


refinery Handoff

# Merge queue tracking
last_processed_branch: null
branches_merged_this_cycle: 0


Polecat template: move startup announcement into molecule

Template has STARTUP PROTOCOL with 'Announce: beads Polecat furiosa, checking in.' This should be a startup step in the polecat molecule, not prose instruction in CLAUDE.md. The molecule drives behavior, not the template prose.


Digest: mol-deacon-patrol

Patrol 3: all healthy


Keepalive signal from bd/gt commands

Every bd and gt command should touch a keepalive file to signal 'agent is alive/working'.

## Implementation

Touch `<workspace>/.gastown/keepalive.json`:
```json
{"last_command": "bd show gt-99m", "timestamp": "2025-12-18T13:45:00Z"}
```

## Usage by Daemon

- Fresh (< 2 min) → agent is working, skip heartbeat
- Stale (2-5 min) → might be thinking, gentle poke
- Very stale (> 5 min) → likely idle, safe to interrupt

## Benefits

- Zero cost (just file I/O)
- Works during long tool calls
- Doesn't require agent cooperation
- Foundation for smarter backoff strategies


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

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


Agent monitoring and status inference

Agent monitoring with status inference from activity, like PGT.

## Agent Status Enum
```go
type AgentStatus string
const (
    StatusAvailable AgentStatus = "available"
    StatusWorking   AgentStatus = "working"
    StatusThinking  AgentStatus = "thinking"
    StatusBlocked   AgentStatus = "blocked"
    StatusWaiting   AgentStatus = "waiting"
    StatusReviewing AgentStatus = "reviewing"
    StatusIdle      AgentStatus = "idle"
    StatusPaused    AgentStatus = "paused"
    StatusError     AgentStatus = "error"
    StatusOffline   AgentStatus = "offline"
)
```

## Status Sources (priority order)
```go
type StatusSource string
const (
    SourceBossOverride StatusSource = "boss"      // Witness/Mayor sets
    SourceSelfReported StatusSource = "self"      // Agent reports own status
    SourceInferred     StatusSource = "inferred"  // Detected from activity
)
```

## Activity Detection

### Pattern Registry
```go
var activityPatterns = []struct {
    Pattern string
    Status  AgentStatus
}{
    {"Thinking...", StatusThinking},
    {"BLOCKED:", StatusBlocked},
    {"Error:", StatusError},
    // etc
}
```

### Idle Detection
No pane output for N seconds → StatusIdle

### Resource Monitoring (optional)
CPU/memory via os.Process

## New Package
internal/monitoring/
├── types.go      # AgentStatus, StatusReport
├── detector.go   # PatternRegistry, detect from output
├── tracker.go    # Per-agent status tracking
└── idle.go       # Idle timeout detection

## Integration
- Session capture output → monitoring detector
- Status shown in gt status, gt session list

## PGT Reference
gastown-py/src/gastown/monitoring/

## Acceptance Criteria
- [ ] Status enum with 10 states
- [ ] Pattern-based detection from pane output
- [ ] Idle detection with configurable timeout
- [ ] Status visible in CLI output


Fix docs: Formulas are JSON not YAML

The molecular chemistry docs (molecule-algebra.md, molecular-chemistry.md) incorrectly refer to formulas as YAML. Formulas are JSON (.formula.json). Fix all references: .formula.yaml -> .formula.json, 'YAML files' -> 'JSON files', 'formula YAML' -> 'formula JSON', code blocks from yaml to json syntax.


Day 1.4: Create agent beads for core roles

Create agent beads with deterministic IDs:
- gt-mayor (Mayor coordinator)
- gt-witness (per-rig polecat monitor)
- gt-refinery (per-rig merge processor)

Each with role_type, rig, and initial state.

Parent: gt-d0jqp


Polecat template: move session close checklist into molecule steps

Template has prose checklists for 'Before Signaling Done' and 'SESSION CLOSE PROTOCOL'. These should be encoded as tail steps in the polecat molecule, not repeated as prose in CLAUDE.md. Reduces duplication and ensures the steps are actually followed.


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


Merge: gt-ldk8

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


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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 18


Wire up created_by field for beads issues

## Goal
Add actor/creator attribution to beads issues created by gastown.

## Done
- Added CreatedBy field to Issue struct
- Added Actor field to CreateOptions
- Pass --actor to bd create

## Remaining
1. Add ActorString() method to RoleInfo
2. Update beads.Create() callers to pass Actor
3. Update direct bd create exec calls to add --actor

## Context
Beads GH #748 added created_by field. Gastown needs to populate it.


Digest: mol-deacon-patrol

Patrol 16: all clear


Design future federation model

Document how remote/federated refinery would work in the future.

## Options to document
1. Git bundles - portable patches, no branches on origin
2. Dedicated integration branch pattern (integration/*)
3. Hybrid - local for same-machine, bundles for remote

## Deliverable
Design doc in docs/federation-refinery.md or similar.
Not implementing now - just capturing the design for when needed.


OSS Launch Readiness

Track all issues blocking or affecting OSS launch quality.

P0 Blocker:
- gt-ofl2: ProcessMRFromQueue not implemented

P1 Must Fix:
- gt-vzic: README missing prerequisites (tmux)
- gt-xbfw: Missing OSS files (CONTRIBUTING, etc.)
- gt-wexr: Polecat role swarm terminology
- gt-6n13: Competing molecule mechanisms
- gt-3abj: go install may fail

P2 Should Fix:
- gt-qj12: Obsolete beads cleanup
- gt-zn9m: Error suppression patterns
- gt-9uxr: Test coverage gaps
- gt-fm75: os.Exit in library code
- gt-yewf: Mismatched startup protocols
- gt-1z4m: Undocumented gt swarm
- gt-bho9: stderr suppression
- gt-rxsh: Merge model confusion
- gt-5ipl: Witness role commands

P3 Nice to Have:
- gt-t5mz: Hardcoded values


Digest: mol-deacon-patrol

Patrol 10: OK


Infrastructure formulas for dog tasks

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


Execute registered plugins

Execute registered plugins.

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

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

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

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

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

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


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

Patrol 15: All healthy


Digest: mol-deacon-patrol

Patrol 4: quiet


Digest: mol-deacon-patrol

Patrol complete: 0 mail, Mayor+2 witnesses+2 refineries healthy, 3 polecats working (gastown), no orphans, gc N/A


MR ID generation: prefix-mr-hash convention

Generate merge-request IDs following the convention: <prefix>-mr-<hash>

Example: gt-mr-abc123 for a gastown merge request.

This distinguishes MRs from regular issues while keeping them in the same namespace.
The hash should be derived from branch name + timestamp for uniqueness.

Implement: GenerateMRID(prefix, branch string) string

Reference: docs/merge-queue-design.md#id-convention


Witness session cycling and handoff

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

## Session Cycling Protocol

```markdown
## Session Cycling

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

### Handoff Protocol

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

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

## Active Workers
<list workers and status>

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

## Recent Actions
<last 3-5 actions>

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

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

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

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

### On Fresh Session Start

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

## Implementation

Add to WITNESS_CLAUDE.md template.


Day 3.5: Test polecat → refinery → merged flow

Integration test:
1. Spawn polecat with work
2. Polecat completes (updates state, closes bead)
3. Witness detects completion
4. Witness sends MERGE_READY
5. Refinery processes and merges
6. MERGED signal received

Parent: gt-hwka3


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


Swarm cleanup: delete merged polecat branches and reset state

After a swarm completes and branches are merged, leftover state remains:

## Current Problem

1. **Remote branches not deleted** - polecat/* branches stay on origin after merge
2. **Polecat clones not reset** - still on old branch with completed work
3. **No cleanup command** - manual cleanup required

## Observed After Swarm

Remote branches still present:
- origin/polecat/Morsov
- origin/polecat/Nux
- origin/polecat/Rictus
- origin/polecat/Slit
- origin/polecat/Toast

## Proposed Solution

Add cleanup commands:

1. gt swarm cleanup <swarm-id> - Clean up after swarm completion
   - Delete remote polecat branches that were merged
   - Reset polecat clones to main
   - Clear issue assignments

2. gt polecat reset <rig>/<polecat> - Reset single polecat
   - git checkout main && git pull
   - Delete local polecat branch
   - Clear current issue assignment

3. Auto-cleanup option on gt session stop --cleanup

## Manual Cleanup For Now

git push origin --delete polecat/Nux polecat/Toast ...
cd polecats/Nux && git checkout main && git pull


Digest: mol-deacon-patrol

Patrol 7: Interrupted, routine


Digest: mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 4: 8 sessions active, all healthy


Digest: mol-deacon-patrol

Patrol: TRACER BULLET SUCCESS - gt-oiv0 merged to main, furiosa completed and exited cleanly, 0 polecats now, all agents up


Remove lifecycle intent parsing from Go

daemon/lifecycle.go parses mail subjects with regex looking for restart/shutdown/cycle keywords, then executes actions. Fix: use structured message types in mail body instead of parsing subjects. Go reads action field, does not interpret text.


context-check

Assess own context usage. If high, prepare for handoff.


Update architecture documentation

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

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

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


gt mol attach: Auto-detect agent from cwd when single arg provided

## Current Behavior

gt mol attach requires 2 args:
  gt mol attach <agent-bead-id> <molecule-id>

## Expected Behavior

When called with 1 arg from an agent working directory:
  gt mol attach <molecule-id>

Should auto-detect the agent from cwd (same detection used by gt mail, bd, etc.)
and attach the molecule to that agent hook.

## Example

From ~/gt/gastown/mayor/rig:
  gt mol attach gt-y14l7
  -> detects mayor role
  -> attaches gt-y14l7 to gt-mayor hook

## Implementation

1. Check arg count
2. If 1 arg, call role detection from cwd
3. Resolve agent bead ID from role (gt-mayor, gt-witness-gastown, etc.)
4. Proceed with attachment

This makes the common case (attaching work to yourself) ergonomic.


Digest: mol-deacon-patrol

Patrol 20: healthy - handoff cycle


Digest: mol-deacon-patrol

Patrol 13: quiet


HOP: Skill vectors on work items

Add skill embeddings to work items for capability-based matching. See ~/ai/stevey-gastown/hop/CONTEXT.md. Post-v0.1 work.


Remove bd sync instruction from polecat startup workflow

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

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

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

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

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

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


Remove redundant gt prime SendKeys from crew commands

The crew commands (gt crew at, gt crew restart) still send 'gt prime' via SendKeys after session creation:
- internal/cmd/crew_at.go:97, 121
- internal/cmd/crew_lifecycle.go:202

This is now redundant because SessionStart hook handles priming automatically.

**Low priority** - these aren't causing bugs (just duplicate work), unlike the spawn race condition that was fixed. Can be cleaned up when convenient.


Document session cycling protocol in all templates

Add explicit lifecycle request protocol to all agent templates.

## Problem
Templates mention 'request session refresh' but don't show HOW.
Agents don't know the protocol for requesting a cycle.

## Protocol to document
1. Write handoff mail to self (for continuity)
2. Set requesting_cycle=true in state.json
3. Send LIFECYCLE mail to deacon/:
   Subject: 'LIFECYCLE: <role> requesting cycle'
   Body: Reason for cycle request

## Templates to update
- prompts/roles/polecat.md
- prompts/roles/crew.md
- prompts/roles/witness.md
- prompts/roles/refinery.md

## Also add
- Example state.json location for each role
- When to request cycle (context full, work complete, etc.)
- What happens after (daemon kills, respawns, new session primes)


Burn-or-loop step execution

Fix step completion detection in patrol formulas. Ensure done() properly clears the molecule and triggers burn. Currently wisps accumulate because this step doesn't complete.


Clean up duplicate patrol protos (gt-qflq, gt-iep9)

There are duplicate protos for patrol molecules:

## Duplicates

| Old Proto | New Proto | Name |
|-----------|-----------|------|
| gt-qflq | mol-witness-patrol | mol-witness-patrol |
| gt-iep9 | mol-deacon-patrol | mol-deacon-patrol |

The old gt-* prefix protos were created before the formula cooking system.
The new mol-* prefix protos were created by `bd cook`.

## Action

1. Close or delete the old gt-* protos
2. Update any references to use the new mol-* protos
3. Verify `bd mol list` shows clean output

## Root Cause

The bd cook command uses the formula name as the proto ID (mol-*),
not the project prefix (gt-*). This is probably correct behavior,
but means we have legacy protos to clean up.


Digest: mol-deacon-patrol

Patrol #18: Stable


Digest: mol-deacon-patrol

Patrol 9: All green


Test Patrol for Bonding

Parent issue for mol bond CLI test


mol-polecat-arm

Single polecat inspection and action cycle.

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

## Variables

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

## Steps

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

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

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

### assess
Categorize polecat state.

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

Calculate: minutes since last activity.
Needs: capture

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

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

Needs: assess

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

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

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

Record decision and rationale.
Needs: load-history

### execute
Take the decided action.

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

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

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

**none**: No action needed.

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

## Output

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

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

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


Digest: mol-deacon-patrol

Patrol cycle 13: All healthy


Digest: mol-deacon-patrol

Patrol 5: all clear


gt witness: Witness management commands

Add 'gt witness' command group for witness lifecycle management.

Subcommands:
- gt witness start [rig] - Start witness for a rig
- gt witness stop [rig] - Stop witness
- gt witness status [rig] - Show witness status
- gt witness attach [rig] - Attach to witness session

Witness monitors polecats and handles:
- Idle detection and cleanup
- Session health checks
- Nudging stuck agents


Test molecule

Test


Digest: mol-deacon-patrol

Patrol #7: Stable


Cross-project dependency workflow (Gas Town side)

Gas Town integration for cross-project dependencies.

## Components
- gt-zniu: gt park command (park molecule on external dep)
- gt-in3x: gt spawn --continue (resume parked molecule)
- gt-5uf3: Patrol auto-resume (future)

## Design Doc
See: docs/cross-project-deps.md

## Depends on Beads
- bd-h807: Cross-project dependency support (epic)

## Launch Plan
Phase 1 (launch): gt park + gt spawn --continue (manual resume)
Phase 2 (later): Patrol auto-resume


Task A: Setup foundation


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


Remove keepalive file infrastructure

The keepalive mechanism (~/gt/daemon/activity.json) is deprecated in favor of feed-based wake.

TODO:
1. Remove keepalive.TouchTownActivity() calls from gt commands
2. Remove keepalive.ReadTownActivity() from daemon
3. Delete internal/keepalive package
4. Update daemon to use longer base heartbeat (recovery-focused)

Whitelist consideration: Some read-only commands might need to wake (TBD - none identified yet)


Test patrol queue feature


Condition evaluator for gates and loops

Implement mechanical condition evaluation:
- step.status == 'complete'
- step.output.field == value
- children(step).all(status == 'complete')
- file.exists(path), env.VAR

Keep decidable: no arbitrary code, bounded evaluation.


gt feed --follow: Town-level activity stream

Town-native command for aggregated activity feed.

Wraps bd activity --town with Gas Town conveniences:
- gt feed --follow         # Stream all rig activity
- gt feed --rig gastown    # Filter to specific rig
- gt feed --convoy hq-xxx  # Filter to convoy's tracked issues

Essential for Mayor/Deacon visibility into cross-rig work.

Depends on: bd-dx6e (bd activity --town)
Related: hq-7h8jx (Convoy System epic in town beads)


Refinery Patrol Cycle


Digest: mol-deacon-patrol

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


Extract magic values to named constants

Magic strings and numbers throughout codebase:

Shells list repeated 4x:
- start.go:729, 773, 907
- crew_helpers.go
Pattern: []string{"bash", "zsh", "sh", "fish", "tcsh", "ksh"}

Timing values:
- time.Sleep(500 * time.Millisecond) in multiple places
- WaitForCommand 15*time.Second
- WaitForShellReady 5*time.Second
- Debounce 100ms default

Other magic values:
- "gt-" session prefix
- priority = 2 default
- Mail preview length 500 chars
- Heartbeat ages 5min/15min
- Divergence thresholds 10/50 commits

Suggestion: Add to constants/constants.go:
- SupportedShells
- ShutdownNotifyDelay, ClaudeStartTimeout, ShellReadyTimeout
- SessionPrefix
- DefaultPriority
- MailPreviewMaxLength


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.


Day 1.1b: Add type=role to bead schema

Add role as a valid bead type in the schema.

Role beads define agent behavior:
- Priming instructions (from current CLAUDE.md content)
- default_molecule field
- capabilities list

This enables Day 1.5 (creating role beads from CLAUDE.md).

Must be done alongside type=agent schema work.


Documentation humility pass

Update documentation with humble framing.

## Changes Needed

### README.md

- Add "Experimental" or "Alpha" badge
- Clarify current state vs future vision
- List what works vs what is planned
- Include honest limitations section

### Architecture docs

- Mark autonomous features as "planned"
- Distinguish implemented from designed
- Add "Current Status" sections

### CLAUDE.md files

- Remove claims about autonomous operation (where not true)
- Add "v0.1" qualifiers to features
- Be honest about manual steps required

## Tone

NOT: "Gas Town automatically manages agent lifecycles"
YES: "Gas Town provides infrastructure for agent lifecycle management.
     v0.1 requires some manual coordination."

NOT: "The Refinery processes merges autonomously"
YES: "The Refinery is designed for autonomous merge processing.
     v0.1 demonstrates the pattern with manual triggering."

## Files to Review

- README.md
- docs/architecture.md
- docs/quickstart.md (if exists)
- CLAUDE.md files for all roles


Digest: mol-deacon-patrol

Patrol 8: Quiet


Polecat prompting: gt mq submit on completion

Update Polecat CLAUDE.md prompting to:

1. On task completion, run: gt mq submit --issue <id>
2. This creates a merge-request bead in the queue
3. Engineer will process it

The Polecat self-reports completion to the merge queue.


Overseer Crew: User-managed persistent workspaces

## Overview

Crew workers are the overseer's (human's) personal workspaces within a rig. Unlike polecats which are witness-managed and ephemeral, crew workers are:

- **Persistent**: Not auto-garbage-collected
- **User-managed**: Overseer controls lifecycle
- **Long-lived identities**: dave, emma, fred - recognizable names
- **Gas Town integrated**: Mail, handoff mechanics work
- **Tmux optional**: Can work in terminal directly

## Directory Structure

```
<rig>/
  polecats/       # Managed workers (witness controls)
  refinery/       # Merge queue processor
  witness/        # Pit boss
  crew/           # Overseer's personal workspaces
    dave/         # Full clone, persistent
    emma/         # Full clone, persistent
    fred/         # Full clone, persistent
```

## Key Differences from Polecats

- Location: crew/ instead of polecats/
- Lifecycle: User-managed, not witness-managed
- Auto-cleanup: Never (polecats auto-cleanup on swarm land)
- Issue assignment: Optional (polecats require it)
- Tmux: Optional (polecats require it)
- Mail & Handoff: Yes for both
- Identity: Persistent (polecats are ephemeral)

## CLI Commands

- gt crew add <name> [--rig <rig>] - Create crew workspace
- gt crew list [--rig <rig>] - List crew workspaces
- gt crew at <rig>/<name> - Attach to workspace (start session)
- gt crew attach <name> - Attach (infer rig from cwd)
- gt crew refresh <name> - Handoff + restart (context cycling)
- gt crew remove <name> [--force] - Remove workspace
- gt crew status [<name>] - Show workspace status

## Design Notes

- Crew workers use full git clones (not worktrees)
- Optional beads integration via BEADS_DIR
- Mail-to-self handoff works for context cycling
- No witness monitoring or nudging
- No automatic issue assignment required

## Background

Users often maintain separate repo clones for serial agent work. This is tedious to set up manually. Crew workspaces bring these into Gas Town's infrastructure while keeping user control.


attached_args: Refactor runStartCrew into focused helper functions

Break up the 155-line runStartCrew function in start.go.

## Files to modify
- internal/cmd/start.go

## Current structure (lines 638-792)
runStartCrew does:
1. Parse crew target (rig/name)
2. Load rig config
3. Get/create crew workspace
4. Create/attach tmux session
5. Set environment variables
6. Apply theming
7. Start Claude

## Refactoring plan
Extract these helpers:
```go
func parseCrewTarget(args []string) (rigName, crewName string, err error)
func ensureCrewWorkspace(rig *rig.Rig, crewName string) (*crew.CrewWorker, error)
func startCrewSession(worker *crew.CrewWorker, opts CrewStartOpts) error
```

## Acceptance criteria
- [ ] runStartCrew reduced to <60 lines
- [ ] 3 helper functions extracted
- [ ] Each helper is <50 lines
- [ ] No change in behavior
- [ ] go test ./internal/cmd/... passes
- [ ] Manual test: gt start crew works correctly


Bug: gt sling doesn't update agent bead hook_bead field

gt sling marks task as pinned with assignee, but doesn't update the agent bead's hook_bead field. Agent beads show hook_bead: null even after slinging. This prevents agents from knowing they have work on their hook.


Merge: gt-rixa

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


Digest: mol-deacon-patrol

Patrol 5: all healthy