Merge: valkyrie-1767074338488

attached_args: Code review

branch: polecat/valkyrie-1767074338488
target: main
source_issue: valkyrie-1767074338488
rig: gastown

CODE REVIEW (furiosa): REJECT

Issue: Commit modifies CLAUDE.md which is gitignored on main.

Findings:
1. CLAUDE.md is in .gitignore (clone-specific file)
2. CLAUDE.md is NOT tracked on main branch
3. Polecat manager has installCLAUDETemplate() to generate this file locally per worktree
4. The commit adds a file that should not be committed

Recommendation: Do not merge. CLAUDE.md should be locally generated, not committed.

This merge request has no valid changes to merge.


Witness: Reduce chattiness, increase autonomy

Witness is spamming Mayor with routine status:
- 'Polecat X processed' - routine, no action needed
- 'Idle polecats: X needs work' - wrong direction

Witness should be a local sheriff:
1. Handle routine lifecycle autonomously (don't report)
2. Only escalate genuine problems requiring human/mayor intervention
3. Use convoy system for batch 'work complete' notifications
4. Never ask Mayor to assign work - either do it yourself or let polecats idle

Remove these mail types:
- POLECAT_PROCESSED (routine)
- IDLE_POLECAT (wrong escalation direction)

Keep these:
- ESCALATION (genuine problem)
- BLOCKED (needs human decision)
- CRASH_RECOVERY (informational, useful)


Digest: mol-deacon-patrol

Patrol 15: healthy


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 30/1023)


Move disk 3: C → A

Move disk 3 from peg C to peg A. (Move 44/1023)


Digest: mol-deacon-patrol

Patrol 20


Digest: mol-deacon-patrol

Patrol #19: Dog pool healthy, 1 idle.


Digest: mol-deacon-patrol

Patrol 5 complete. All healthy.


Merge: toast-mjw7062w

branch: polecat/toast-mjw7062w
target: main
source_issue: toast-mjw7062w
rig: gastown
agent_bead: gt-gastown-polecat-toast


Refinery emits activity events

Refinery emits events to activity stream for MQ lifecycle:

Events to emit:
- merge_started: When refinery begins processing an MR
- merged: When MR successfully merged to main
- merge_failed: When merge fails (conflict, tests, etc.)
- merge_skipped: When MR skipped (already merged, etc.)

Events should include: MR ID, worker, branch, timestamp, reason (for failures)

This replaces stats tracking in .runtime/refinery.json


Digest: mol-deacon-patrol

Patrol 19: All clear


Remove 'spawn' terminology from molecular chemistry

Clean all docs and code to present ONLY current terminology. No migration paths, no "old vs new" tables, no deprecated flags. The codebase should read as if the current design was always the design.

**Terminology rules:**
- spawn = polecats/workers ONLY
- pour = create persistent mol
- wisp = create ephemeral wisp
- run = create and execute

**Scope:**
- Remove all "Old → New" migration tables
- Remove deprecated flag documentation (--persistent, etc.)
- Remove chemistry-design-changes.md entirely (it is a migration doc)
- Clean all docs to use current terminology only
- Rename spawn functions in code that deal with molecules


Merge: toast-mjxpchjl

branch: polecat/toast-mjxpchjl
target: main
source_issue: toast-mjxpchjl
rig: gastown
agent_bead: gt-gastown-polecat-toast


Digest: mol-deacon-patrol

Patrol cycle 6: All healthy.


Digest: mol-deacon-patrol

Patrol cycle 9: All healthy.


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Move disk 3: B → C

Move disk 3 from peg B to peg C. (Move 132/1023)


mol-deacon-patrol


gt handoff: Unified agent lifecycle command

## Summary

Unified `gt handoff` command for ALL agent types to request lifecycle actions.

## Usage

gt handoff              # Context-aware default
gt handoff --shutdown   # Terminate, cleanup, don't restart
gt handoff --cycle      # Restart with handoff mail
gt handoff --restart    # Fresh restart, no handoff

## Context-Aware Defaults

| Agent Type | Default | Reason |
|------------|---------|--------|
| Polecat | --shutdown | Ephemeral, work is done |
| Witness | --cycle | Long-running, context full |
| Refinery | --cycle | Long-running, context full |
| Mayor | --cycle | Long-running, context full |
| Crew | (sends mail only) | Human-managed |

## What gt handoff Does

1. **Verify safe to stop**
   - Git state clean (no uncommitted changes)
   - Work handed off (PR exists for polecats)

2. **Send handoff mail to self** (for cycle/restart)
   - Captures current state
   - New session will read this

3. **Send lifecycle request to manager**
   - Polecats/Refinery → Witness
   - Witness/Mayor → Daemon
   - Format: mail to <manager> with action type

4. **Set state: requesting_<action>**
   - Lifecycle manager checks this before acting

5. **Wait for termination**
   - Don't self-exit - let manager kill session
   - Ensures clean handoff

## Lifecycle Request Flow

Agent                           Lifecycle Manager
  |                                    |
  | 1. gt handoff --cycle              |
  |    a. Verify git clean             |
  |    b. Send handoff mail to self    |
  |    c. Set requesting_cycle=true    |
  |    d. Send lifecycle request       |
  |------------------------------------→|
  |                                    |
  |                   2. Receive request
  |                   3. Verify state  |
  |                   4. Kill session  |
  |                   5. Start new     |
  |                      (for cycle)   |
  |                                    |
  |         New session reads handoff  |
  |         Resumes work               |

## Who Manages Whom

| Agent | Sends lifecycle request to |
|-------|---------------------------|
| Polecat | <rig>/witness |
| Refinery | <rig>/witness |
| Witness | daemon/ |
| Mayor | daemon/ |

## Implementation

1. Detect current role (polecat, witness, refinery, mayor, crew)
2. Apply context-aware default if no flag specified
3. Run pre-flight checks (git clean, work handed off)
4. Send handoff mail to self (if cycling)
5. Send lifecycle request to appropriate manager
6. Set requesting_<action> in state.json
7. Wait (manager will kill us)

## For Polecats (--shutdown)

Additional cleanup after kill:
- Witness removes worktree
- Witness deletes polecat branch
- Polecat ceases to exist

## Related Issues

- gt-99m: Daemon (handles Mayor/Witness lifecycle)
- gt-7ik: Ephemeral polecats (polecat cleanup)
- gt-eu9: Witness session cycling


Digest: mol-deacon-patrol

Patrol complete: healthy


Move disk 2: A → C

Move disk 2 from peg A to peg C. (Move 554/1023)


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


Move disk 3: A → B

Move disk 3 from peg A to peg B. (Move 580/1023)


Day 4.2: Implement gt polecat nuke command

Add gt polecat nuke <name> command:
- Kill the Claude session
- Delete the worktree
- Delete the branch
- Remove agent bead
- Full cleanup post-merge

Parent: gt-4a2qt


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 387/1023)


Day 3.6: Polecat closes steps for activity feed

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

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

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

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

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

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

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


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 390/1023)


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 71/1023)


generate-summary

Summarize patrol cycle for digest.

Needs: save-state


Merge: dementus-1767146229184

branch: polecat/dementus-1767146229184
target: main
source_issue: dementus-1767146229184
rig: gastown


Digest: mol-deacon-patrol

Patrol 3: All healthy


Move disk 6: C → B

Move disk 6 from peg C to peg B. (Move 672/1023)


Digest: mol-deacon-patrol

Patrol cycle 72: All healthy


Digest: mol-deacon-patrol

Patrol #8: Stable


Digest: mol-deacon-patrol

Patrol #12: Stable


Merge: gt-5af.2

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


Use cmd.OutOrStdout instead of fmt.Print in refinery

refinery/manager.go and refinery/engineer.go use fmt.Print/Println directly for user output (30+ occurrences). This breaks testability and doesn't follow cobra best practices. Should use cmd.OutOrStdout() or pass an io.Writer.

Affected files:
- internal/refinery/manager.go (lines 222, 360-361, 369, 387-393, 519, 537, 672)
- internal/refinery/engineer.go (lines 190-211, 249, 294-297, 325-353, 362-366)


Digest: mol-deacon-patrol

Patrol 2 complete. All agents healthy.


Digest: mol-deacon-patrol

Patrol 17: All healthy.


Recovery: Detect orphaned merged polecats

Safety net for when Refinery misses sending lifecycle notification.

## Detection Points

**Witness polecat-scan**:
- For each polecat in `mr_submitted` state:
  - Check MR status: `gt mq status <mr-id>`
  - If MR is closed/merged but polecat state is still mr_submitted:
    - Update polecat state to `merged`
    - Log recovery action

**Deacon orphan-check**:
- Query all closed MRs
- Cross-reference with polecat states
- If merged MR but polecat not in merged/retired state:
  - Send correction to Witness
  - Log for metrics (indicates Refinery notification missed)

## Acceptance
- Orphaned polecats detected and corrected
- Recovery is logged for monitoring
- No work lost due to missed notifications


Work on gt-o9j: Fix tmux status bar polecat count - exclu...

Work on gt-o9j: Fix tmux status bar polecat count - exclude static roles (mayor, deacon, witnesses, refineries, docs, hop). Run 'bd show gt-o9j' for details.


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 193/1023)


Digest: mol-deacon-patrol

Patrol 10: all healthy, sessions up


Add timeouts to convoy panel subprocess calls

convoy.go spawns bd and sqlite3 without timeouts. If these hang, the TUI freezes. Add 5-second context timeouts.


Digest: mol-deacon-patrol

Patrol cycle 49: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Refinery needs branch visibility: Convert to worktree or push branches

The refinery cannot see polecat branches because it is a separate clone, not a worktree.

## Problem
- Polecats are worktrees of mayor/rig (correct, per gt-4u5z)
- Refinery is still a separate clone at refinery/rig (not converted)
- Polecat branches are local to mayor/rig, invisible to refinery

## Decision (2025-12-25)
**Use a shared bare repo as the single git source of truth.**

```
gastown/
├── .repo.git/           ← Bare repo (no working tree, invisible base)
├── mayor/rig/           ← Worktree (human workspace)
├── polecats/
│   └── Toast/           ← Worktree on polecat/Toast
├── refinery/rig/        ← Worktree on main (can see all branches!)
└── crew/max/            ← Worktree or separate clone (TBD)
```

**Why bare repo:**
- No working directory to accidentally work in
- Standard git pattern (how servers work)
- All worktrees share branch visibility
- Refinery on main can merge polecat branches directly

## Implementation
1. Create `.repo.git` as bare clone
2. Convert refinery to worktree of .repo.git on main
3. Convert polecats to worktrees of .repo.git
4. Optionally convert mayor/rig (or keep as worktree)
5. Update gt rig init for new rigs
6. Write migration for existing rigs

## Evidence
Tracer bullet 2025-12-23: Refinery could not see polecat/tracer until pushed to origin.


Merge: furiosa-1767081103575

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


gt mail check: Check for new mail

Add `gt mail check` command.

```
gt mail check [--quiet] [--inject]
```

- --quiet: Only output if new mail (for scripts/hooks)
- --inject: Send notification to running session (future)

**Implementation:**
- Add `checkCmd` to internal/cmd/mail.go
- Count unread messages in inbox
- Output: 'N new message(s)' or nothing if --quiet and empty

Simple command, good first task.


Witness updates: Remove issue filing proxy

Update Witness prompting to remove issue filing proxy, since polecats now have direct beads access.

## Remove from Witness Prompting

The following is NO LONGER Witness responsibility:
- Processing polecat 'file issue' mail requests
- Creating issues on behalf of polecats
- Forwarding issue creation requests

## Add: Legacy Request Handling

If Witness receives an old-style 'please file issue' request:

1. Respond with update:
   town inject <polecat> "UPDATE: You have direct beads access now. Use bd create to file issues yourself."

2. Do not file the issue - let the polecat learn the new workflow.

## Keep in Witness Prompting

- Monitoring polecat progress
- Nudge protocol
- Pre-kill verification
- Session lifecycle management


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 997/1023)


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 657/1023)


Design: CI test infrastructure and approach

Design decisions for CI test infrastructure.

## Decisions Made

### 1. Test Framework
**Decision**: Go's standard testing with `//go:build integration` tag

Rationale:
- Familiar to Go developers
- Easy to run separately: `go test -tags=integration ./...`
- Can have different timeouts for unit vs integration
- No external test framework dependencies

### 2. Temp Directory Strategy
**Decision**: `t.TempDir()` per test

Rationale:
- Auto-cleanup (no manual defer needed)
- Test isolation - each test gets fresh state
- Easy debugging - can add `t.Setenv("KEEP_TEMP", "1")` to preserve

### 3. Git Repo Handling
**Decision**: Create minimal repos on-the-fly with `git init`

Rationale:
- Faster than cloning fixtures
- No external dependencies
- Tests exactly what users do
- Helper: `createTestGitRepo(t, name)`

### 4. bd Daemon
**Decision**: Run bd commands directly without daemon

Rationale:
- bd CLI works fine for basic operations
- Simpler test setup
- Daemon adds complexity without testing benefit for install flow

### 5. CI Integration
**Decision**: Separate job with path filtering

- Runs on: push to main, PRs touching install/rig/config/routing code
- Timeout: 5 minutes (vs 2 min for unit tests)
- Installs bd from beads repo before running

## Implementation
- Created: `internal/cmd/install_integration_test.go`
- Updated: `.github/workflows/ci.yml` with integration job

## Test Cases Implemented
- TestInstallCreatesCorrectStructure
- TestInstallBeadsHasCorrectPrefix
- TestInstallIdempotent
- Helper: createTestGitRepo


Digest: mol-deacon-patrol

P19: stable


Digest: mol-deacon-patrol

Patrol complete: Restarted 5 downed agents (Mayor, 2 Witnesses, 2 Refineries). All systems now healthy.


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 459/1023)


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 378/1023)


Use atomic write pattern for state files

attached_args: Atomic write pattern for state files

Prevent data loss from concurrent state file writes using atomic write pattern.

## Files to modify
- internal/witness/manager.go
- internal/refinery/manager.go
- internal/crew/manager.go
- internal/swarm/manager.go

## Problem
State is saved directly to file - if process crashes mid-write, file corrupts.

## Implementation
Replace direct writes with atomic pattern:
```go
func atomicWriteJSON(path string, v interface{}) error {
    data, err := json.MarshalIndent(v, "", "  ")
    if err != nil {
        return err
    }
    tmpFile := path + ".tmp"
    if err := os.WriteFile(tmpFile, data, 0644); err != nil {
        return err
    }
    return os.Rename(tmpFile, path)  // Atomic on POSIX
}
```

## Acceptance criteria
- [ ] atomicWriteJSON helper created (in internal/util or similar)
- [ ] All 4 manager saveState methods use atomic writes
- [ ] .tmp files cleaned up on success
- [ ] go test ./... passes
- [ ] Manual test: state files survive kill -9


Digest: mol-deacon-patrol

Patrol cycle 13: All 6 agents healthy


mol-ready-work variants: safe vs aggressive

## Summary

Create two variants of mol-ready-work:

### mol-ready-work-safe (default)
- PRs: review and comment, but require human approval for merge
- Issues: triage only, don't auto-close
- Beads: implement but create PR instead of pushing to main

### mol-ready-work-aggressive
- PRs: can approve and merge directly
- Issues: can close duplicates/invalid
- Beads: can push directly to main

## Implementation
Could be a single molecule with a `{{mode}}` variable, or two separate protos.

## Parent
Part of gt-tnca (mol-ready-work epic)


mol-refinery-patrol

Merge queue processor patrol loop.

The Refinery is the Engineer in the engine room. You process polecat branches, merging them to main one at a time with sequential rebasing.

**The Scotty Test**: Before proceeding past any failure, ask yourself: "Would Scotty walk past a warp core leak because it existed before his shift?"

## Merge Flow

The Refinery receives MERGE_READY mail from Witnesses when polecats complete work:

```
Witness                    Refinery                      Git
   │                          │                           │
   │ MERGE_READY              │                           │
   │─────────────────────────>│                           │
   │                          │                           │
   │                    (verify branch)                   │
   │                          │ fetch & rebase            │
   │                          │──────────────────────────>│
   │                          │                           │
   │                    (run tests)                       │
   │                          │                           │
   │                    (if pass)                         │
   │                          │ merge & push              │
   │                          │──────────────────────────>│
   │                          │                           │
   │ MERGED                   │                           │
   │<─────────────────────────│                           │
   │                          │                           │
```

After successful merge, Refinery sends MERGED mail back to Witness so it can
complete cleanup (nuke the polecat worktree).


Immediate daemon notification on lifecycle request

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

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

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

## Proposed Solutions

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

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

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

Recommend Option A for simplicity.

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


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

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

## Variables

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


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 139/1023)


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 462/1023)


Move disk 3: A → B

Move disk 3 from peg A to peg B. (Move 244/1023)


Digest: mol-deacon-patrol

Patrol 15: Quiet


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.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


gt-gastown-polecat-testcat3

gt-gastown-polecat-testcat3

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


Digest: mol-deacon-patrol

Patrol cycle 2: all quiet, agents healthy


Digest: mol-deacon-patrol

Patrol 2: Routine cycle. All rigs healthy. 12 polecats. No incidents.


Move disk 5: A → B

Move disk 5 from peg A to peg B. (Move 976/1023)


Digest: mol-deacon-patrol

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


Integration branch management for swarms

Manage integration branches for swarm merging strategy.

## Branch Naming

- Integration branch: `integration/<swarm-id>` (e.g., integration/sw-1)
- Worker branches: `<swarm-id>/<polecat>` (e.g., sw-1/Toast)

## Operations

```go
// Create integration branch at swarm start
func (m *SwarmManager) CreateIntegrationBranch(swarmID string) error
// - Creates from BaseCommit
// - Pushes to origin

// Merge worker branch to integration
func (r *Refinery) MergeToIntegration(swarmID, workerBranch string) error
// - Fetches worker branch
// - Merges to integration/<swarm-id>
// - Handles conflicts (semantic merge)

// Land integration to main
func (r *Refinery) LandToMain(swarmID string) error
// - Merges integration/<swarm-id> to main
// - Pushes to origin
// - Triggers cleanup

// Cleanup branches after landing
func (m *SwarmManager) CleanupBranches(swarmID string) error
// - Deletes integration/<swarm-id> (local + remote)
// - Deletes all <swarm-id>/<polecat> branches
```

## All Workers Same Base

When swarm starts:
1. Record current main HEAD as BaseCommit
2. All polecats branch from BaseCommit
3. Integration branch also starts at BaseCommit

This ensures clean merges within the swarm.

## Reference

PGT: ephemeral.py (create_integration_branch, merge_integration_to_main)


Digest: mol-deacon-patrol

Patrol 153: All healthy, nux respawned


Merge: gt-jzot

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


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 607/1023)


gt polecat remove --all: bulk polecat teardown

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

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

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

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


Digest: mol-deacon-patrol

Patrol 9: quiet


Digest: mol-deacon-patrol

Patrol 16: All healthy


Boot needs CLAUDE.md and directory setup

Boot spawns in ~/gt/deacon but:
1. No ~/gt/deacon/dogs/boot/ directory exists
2. Boot reads Deacon's CLAUDE.md (wrong role context)
3. spawnTmux() doesn't send initial triage prompt

Fix:
- Create ~/gt/deacon/dogs/boot/CLAUDE.md with Boot role instructions
- Update EnsureDir() to create directory on spawn
- Consider sending 'gt boot triage' as initial prompt

Boot should know it's a fresh-each-tick watchdog that:
- Observes Deacon state
- Decides: start/wake/nudge/nothing
- Cleans stale inbox
- Exits (never handoffs)


Merge: slit-1767073379145

attached_args: Code review this merge request

branch: polecat/slit-1767073379145
target: main
source_issue: slit-1767073379145
rig: gastown

CODE REVIEW (valkyrie): REQUEST CHANGES

Critical bugs found in internal/swarm/manager.go:
1. JSON field changed from 'dependents' to 'dependencies' but bd outputs 'dependents'
2. 'hooked' status removed from in_progress handling
3. Assignee field removed from task loading

These changes will break swarm coordination. Polecat_spawn.go fix is correct.

Recommendation: Revert swarm/manager.go changes, keep polecat_spawn.go fix.


MCP beads tools fail from polecat directories

The beads MCP plugin (plugin:beads:beads) fails to find issues when invoked from polecat directories.

## Observed
- Polecat in /gt/gastown/polecats/dementus
- MCP tool: plugin:beads:beads - show (issue_id: 'gt-th7')
- Error: 'bd command failed: Error: no issue found matching gt-th7'

## Expected
MCP tools should work the same as running bd directly.

## Note
This may be related to gt-tmm (beads sync issue) rather than an MCP-specific bug. The MCP tool uses bd under the hood, and bd can't find the issue because the polecat's beads database is stale.


Agent protocol integration test

End-to-end test: polecat completes work → sends WORK_COMPLETE → witness receives and sends POLECAT_READY → refinery merges → sends MERGE_SUCCESS → witness cleans up polecat. All via structured protocol messages.


Digest: mol-deacon-patrol

Patrol 4: 8 sessions active, all healthy


Digest: mol-deacon-patrol

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


Add tests for critical untested packages

Several packages have no tests:

High priority (critical functionality):
- internal/lock/ - file locking
- internal/mail/router.go, mailbox.go - agent communication
- internal/mrqueue/ - merge request queue
- internal/refinery/ (manager_test.go missing for complex merge logic)

Medium priority:
- internal/claude/ - settings management
- internal/wisp/ - ephemeral workflow
- internal/constants/ - constant values

Low priority:
- internal/style/ - terminal styling

The refinery package is especially concerning - it has complex merge, conflict, and retry logic with no tests.


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 477/1023)


BUG: gt swarm create uses non-existent --mol-type flag on bd update

gt swarm create fails because it tries to use --mol-type=swarm with bd update, but that flag doesn't exist.

## Location
internal/cmd/swarm.go lines 241, 252, 661-662

## Problem
- `bd list --mol-type=swarm` works (flag exists)
- `bd create --mol-type=swarm` works (flag exists)
- `bd update --mol-type=swarm` FAILS (flag doesn't exist)

## Fix Options
1. Add --mol-type flag to bd update command (beads change)
2. Use labels instead of mol-type for swarm marking
3. Only set mol-type during bd create, not update

## Reported By
gus during gt-d46 swarm attempt


Digest: mol-deacon-patrol

Patrol #4: All agents healthy.


Merge: valkyrie-1767106008400

branch: polecat/valkyrie-1767106008400
target: main
source_issue: valkyrie-1767106008400
rig: gastown


Digest: mol-deacon-patrol

Patrol 20


Digest: mol-deacon-patrol

Patrol 45: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Digest: mol-deacon-patrol

Patrol 20 - handoff threshold reached


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


gt doctor: Check settings.json hook consistency across town

## Problem

Settings.json files in different locations can become out of sync, causing session_id
passthrough to fail for some roles but not others. This happened when:
- Town root was updated to use session-start.sh
- Rig root still had old 'gt prime' direct call
- Mayor/rig had mixed state

## Locations to Check

1. `~/gt/.claude/settings.json` (town root - Mayor uses this)
2. `~/gt/<rig>/.claude/settings.json` (rig root - polecats/crew use this)
3. `~/gt/<rig>/mayor/rig/.claude/settings.json` (mayor/rig - source of truth)

## Check Logic

For SessionStart and PreCompact hooks, verify all use `session-start.sh`:
- Must contain `bash ~/.claude/hooks/session-start.sh` (or full path)
- Warn if any use bare `gt prime` without session-start.sh wrapper

## Output

```
gt doctor
...
session-hooks: ✓ All settings.json files use session-start.sh
# or
session-hooks: ✗ ~/gt/gastown/.claude/settings.json uses bare 'gt prime' (missing session_id passthrough)
```

## Fix Suggestion

When inconsistency found, suggest:
```
Hint: Update SessionStart/PreCompact hooks to use 'bash ~/.claude/hooks/session-start.sh'
      This enables session_id passthrough for gt seance discovery.
```

## Related

- session-start.sh extracts session_id from Claude Code stdin JSON
- gt prime outputs [GAS TOWN] metadata line for seance
- gt seance discovers sessions from .events.jsonl


gt crew remove: Does not close agent bead

When running 'gt crew remove <name>', the command removes the crew workspace directory but does not close the associated agent bead (gt-<rig>-crew-<name>).

This leaves orphaned agent beads in the system after crew removal.

The remove command should close the agent bead with a reason like 'Crew workspace removed'.


Digest: mol-deacon-patrol

Patrol cycle 19: All healthy.


Digest: mol-deacon-patrol

Patrol cycle 18: nominal


Mol Mall: Formula marketplace and aspect composition

## Summary

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

## Key Insight

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

## Architecture

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

## Formula Types

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

## Aspect Composition (New Cooking Capability)

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

Aspects declare injection points:

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

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

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

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

## The Mall Index

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

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

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

## Implementation Phases

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

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

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

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

## Open Questions

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

## Deferred Until

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

Then the mall becomes valuable for sharing patrol customizations.

## Supersedes

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

## Related

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

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


BUG: gt polecat nuke also tries to nuke rig/rig (e.g. gastown/gastown)

When running 'gt polecat nuke <name> <rig> --force', it successfully nukes the polecat but then also attempts to nuke '<rig>/<rig>' (e.g. gastown/gastown).

Example output:
  ⚠ Nuking gastown/angharad (--force)...
    ✓ killed session
    ...
  ⚠ Nuking gastown/gastown (--force)...
    ○ worktree already gone

This is harmless but indicates a bug in argument parsing or loop logic.


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 493/1023)


Move disk 3: A → B

Move disk 3 from peg A to peg B. (Move 628/1023)


gt feed: Add convoy dashboard panel for in-progress and recently-landed

## The Insight

Convoys are now the most important unit of work for certain Gas Town users.
The convoy-landing feed is THE view of feature work and fixes actually shipping.

## Current State

gt feed shows:
- Agent tree (top panel): agents by role
- Event stream (bottom panel): issue/molecule activity

Missing: **Convoy status panel**

## Proposed Enhancement

Add a convoy panel showing:

```
┌─🚚 Convoys─────────────────────────────┐
│ IN PROGRESS                            │
│  hq-qrfz4  cv-startup      2/4 ●●○○   │
│  hq-wvqi6  Boot+Polish     3/5 ●●●○○  │
│                                        │
│ RECENTLY LANDED (24h)                  │
│  hq-abc12  Auth refactor   ✓ 2h ago   │
│  hq-def34  API cleanup     ✓ 5h ago   │
└────────────────────────────────────────┘
```

## Components

1. **In-progress convoys**: Open convoys with progress bars (completed/total)
2. **Recently landed**: Convoys that closed in last 24h (configurable)
3. **Quick stats**: Total in-flight, landed today, etc.

## Integration Options

A) New panel in existing TUI (3-panel layout)
B) Dedicated `gt convoy feed` or `gt convoy watch` command
C) Both - convoy panel in main feed + dedicated convoy view

## Why This Matters

The agent tree shows WHO is working.
The event stream shows WHAT is happening.
The convoy panel shows WHAT IS SHIPPING.

For stakeholders, the convoy view is the most important - "what features landed today?"


Merge: dag-1767146241770

branch: polecat/dag-1767146241770
target: main
source_issue: dag-1767146241770
rig: gastown


Digest: mol-deacon-patrol

Patrol 15


Digest: mol-deacon-patrol

Patrol 19: healthy


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


Digest: mol-deacon-patrol

Patrol cycle 76: All healthy


Digest: mol-deacon-patrol

Patrol #7: nominal


Patrol System: Agent lifecycle loops with attachments

Enable Gas Town agents to run continuous patrols, survive crashes, and hand off work across sessions.

## Core Concepts
- **Attachments**: Molecules bound to agent's pinned bead until complete
- **Patrols**: Cyclic molecules that loop (deacon, witness, refinery)
- **Quiescent**: Agents that sleep until triggered (witness, refinery)

## Design Doc
See docs/patrol-system-design.md

## Phases
Phase 1: Foundation (attachment field, daemon detection, mol-deacon-patrol)
Phase 2: Quiescent Agents (wake triggers, witness/refinery patrols)
Phase 3: Callbacks and Plugins (mail protocol, plugin runner)
Phase 4: Polish (gt patrol status, metrics, tuning)

## Key Decisions
- Attachment as field on pinned bead (not edge type, for now)
- Mail-based orchestration for all callbacks
- Queue replacement for heartbeat delivery (not pile-up)
- Burn and respawn for patrol loops (not in-place reset)


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.


CI: GitHub Actions workflow for integration tests

Set up CI to run integration tests:

## Requirements
- Run on PRs touching: internal/cmd/install.go, internal/cmd/rig.go, internal/config/
- Use build tag: //go:build integration
- Timeout: 5 minutes max
- Cache Go modules

## Workflow structure
```yaml
name: Integration Tests
on:
  pull_request:
    paths:
      - 'internal/cmd/install.go'
      - 'internal/cmd/rig.go'
      - 'internal/config/**'
      - 'internal/routing/**'
jobs:
  integration:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
      - run: go test -tags=integration ./...
```


mol-deacon-patrol


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.

## Idle Town Principle

**The Deacon should be silent/invisible when the town is healthy and idle.**

- Skip HEALTH_CHECK nudges when no active work exists
- Sleep 60+ seconds between patrol cycles (longer when idle)
- Let the feed subscription wake agents on actual events
- The daemon (10-minute heartbeat) is the safety net for dead sessions

This prevents flooding idle agents with health checks every few seconds.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 877/1023)


Session ended: gt-gastown-crew-george


Digest: mol-deacon-patrol

Patrol cycle 67: All healthy


Digest: mol-deacon-patrol

Patrol 4: Routine


Digest: mol-deacon-patrol

Patrol 9: routine


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


Phase 3: Callbacks and plugins

Mail-based callback protocol and plugin surface.

## Callbacks
- Polecat → Witness: shutdown requests
- Witness → Deacon: escalations, status
- Crew → Deacon: recycle requests
- Deacon → Mayor: escalations

## Plugins
- .beads/plugins.yaml registry
- Cooldown tracking
- Plugin runner in deacon patrol

Depends: Phase 2


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

Patrol 9: All healthy


CloudRun worker container: Dockerfile and entrypoint

## Overview

Docker container image for Cloud Run workers.

## Dockerfile

```dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o gt ./cmd/gt

FROM ubuntu:22.04

# Install Claude Code
RUN apt-get update && apt-get install -y     curl git nodejs npm     && npm install -g @anthropic-ai/claude-code     && apt-get clean

# Install gt
COPY --from=builder /app/gt /usr/local/bin/gt

# Worker entrypoint
COPY deploy/cloudrun/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 8080
ENTRYPOINT ["/entrypoint.sh"]
```

## Entrypoint

```bash
#!/bin/bash
git config --global user.name "$GIT_USER"
git config --global user.email "$GIT_EMAIL"
exec gt worker serve --port 8080
```

## Files

- `deploy/cloudrun/Dockerfile`
- `deploy/cloudrun/entrypoint.sh`
- `deploy/cloudrun/README.md`

## Dependencies

Depends on: gt-9a2.11 (HTTP server - gt worker serve)


Update docs to reflect molecule-first paradigm

Gas Town is fundamentally a molecule execution engine. Documentation should reflect this more clearly.

## Issues Found

### 1. gt spawn examples show molecule as optional
README.md line 116: `gt spawn --issue <id> # Start polecat on issue`
Should emphasize: polecats execute molecules, not just issues.

### 2. Architecture.md spawn examples inconsistent
Line 344 shows molecule: `gt spawn --issue gt-xyz --molecule mol-engineer-in-box`
Line 1434 shows without: `gt spawn --issue <id>`

### 3. Config vs molecule distinction not clear
outposts.yaml shows static policy - should note when molecules apply.

### 4. Operational molecules section is good but buried
Lines 430-566 cover operational molecules well. Should be more prominent.

## Updates Needed
- [ ] README: Update spawn examples to show molecule usage
- [ ] architecture.md: Ensure all spawn examples include molecules
- [ ] architecture.md: Add section on "when config vs molecule"
- [ ] architecture.md: Move operational molecules higher in document
- [ ] Add principle: "If it requires cognition, it's a molecule"
- [ ] federation-design.md: Note that policy can escalate to mol-outpost-assign

## Key Message
Gas Town doesn't spawn workers on issues. It spawns workers on molecules.
The issue is just the seed data for the molecule execution.


Design: Additional design issues (placeholder)

Placeholder for additional design issues the user wants to raise and work through. Convert to specific subtasks as issues are identified.


Digest: mol-deacon-patrol

Patrol cycle 6: All healthy


Test polecat lifecycle end-to-end

Test the full polecat lifecycle:

1. **Spawn**: Sling a test issue to a polecat
```bash
bd create --title="Test issue for polecat" --type=task
gt sling gt-<id> gastown
```

2. **Execute**: Watch polecat work
```bash
tmux attach -t gt-gastown-<name>
```

3. **Complete**: Polecat should:
   - Close the issue: `bd close gt-<id>`
   - Commit work: `git commit && git push`
   - Send POLECAT_DONE mail to witness

4. **Cleanup**: Witness should:
   - Receive POLECAT_DONE
   - Verify git state clean
   - Kill session and remove worktree

Success: Issue closed, PR merged, polecat cleaned up.


Digest: mol-deacon-patrol

Patrol 20: all clear, handoff due


Move disk 4: A → C

Move disk 4 from peg A to peg C. (Move 968/1023)


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 167/1023)


Digest: mol-deacon-patrol

Patrol 8: Routine


Witness should nuke polecats after completion, not leave idle

## Problem
Polecats are supposed to be ephemeral - fully despawned (nuked) after completing work. Currently the witness:
1. Receives POLECAT_DONE signal
2. Marks polecat as 'idle'
3. Stops there

This leaves zombie polecats with tmux sessions and git worktrees lingering indefinitely.

## Evidence
14 beads polecats sitting 'idle' with stopped sessions after completing work in the Boot+Polish swarm.

## Expected Behavior
After polecat completes (MR submitted or other exit):
1. Witness verifies work is pushed/merged
2. Witness nukes the polecat (session, worktree, branch, agent bead)
3. Polecat no longer exists

Polecats are disposable single-task workers, not persistent like crew.

## Impact
- Accumulating tmux sessions
- Accumulating git worktrees
- Accumulating disk usage
- Confusion about available workers


Digest: mol-deacon-patrol

Patrol 18: all clear


Digest: mol-deacon-patrol

Patrol cycle 17: All healthy


gt hook attach: Accept any bead type including mail

Ensure `gt hook attach <bead-id>` works for:
- Molecules (current)
- Issues
- Mail beads

Implementation in internal/cmd/hook.go


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.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


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


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 529/1023)


Digest: mol-deacon-patrol

Patrol 19: quiet


Digest: mol-deacon-patrol

Patrol cycle 17: all healthy


Digest: mol-deacon-patrol

Patrol 2: All healthy, routine


Activity feed from wisp state: gt patrol status

Enable mayor and gt tool to quickly see what patrol agents are doing.

## Problem

The mayor and gt tool cannot quickly see what the deacon (or other patrol agents) are doing.
Need a way to extract an activity feed from the current wisp state.

## Desired Commands

- gt patrol status: Show current patrol state (step, timing, cycle count)
- gt patrol history: Show recent patrol cycles (from digests)
- gt patrol feed: Live tail of patrol activity

## Data Sources

- .beads-wisp/issues.jsonl: Current wisp with step progress
- .beads/issues.jsonl: Digests from squashed patrols
- heartbeat.json: Last activity timestamp

## Use Cases

1. Mayor checking deacon: Is the deacon doing anything?
2. Debugging hangs: What step is it stuck on?
3. Operator monitoring: Dashboard of patrol health
4. Summaries for handoffs: Auto-generate patrol digest

## Related

- gt-id36: Deacon Kernel
- gt-3x0z: Wisp Molecule Integration


Digest: mol-deacon-patrol

Patrol 4: healthy


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 175/1023)


Digest: mol-deacon-patrol

Patrol 11: Nominal


Move disk 3: C → A

Move disk 3 from peg C to peg A. (Move 164/1023)


Digest: mol-deacon-patrol

Patrol cycle 6: Routine.


Refactor patrol context functions to reduce duplication

In prime.go, three patrol context functions are nearly identical (~100 lines each):
- outputDeaconPatrolContext() - L797-940
- outputWitnessPatrolContext() - L942-1106
- outputRefineryPatrolContext() - L1108-1272

They all:
1. Check for existing patrol molecule
2. Auto-spawn if none exists
3. Display patrol work loop instructions

**Suggested refactor**:
Extract common logic into a helper:
```go
func outputPatrolContext(ctx RoleContext, patrolName string, assignee string) {
    // shared logic
}
```

Then each role-specific function just calls the helper with appropriate parameters.


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 929/1023)


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 591/1023)


Move disk 2: A → C

Move disk 2 from peg A to peg C. (Move 482/1023)


mol-deacon-patrol


Verify final state

All 10 disks now on peg C. Tower intact, all moves were legal.


Human and mail gates

Implement human:<prompt> gate (requires explicit approval command). Implement mail:<pattern> gate (waits for mail matching pattern). These enable async human-in-loop workflows.


Digest: mol-deacon-patrol

Patrol 3: All healthy. 3 rigs, 6 agents. No incidents.


MR bead: Add retry_count and conflict metadata

Extend MR beads to track conflict resolution attempts.

## New Fields
- `retry_count`: Number of conflict-resolution cycles
- `last_conflict_sha`: SHA of main when conflict occurred
- `conflict_task_id`: Link to conflict-resolution task (if any)

## Usage
- Refinery increments retry_count on each conflict
- Priority function uses retry_count as input
- Conflict-resolution task links back to MR

## Implementation
- Update MR creation to include fields
- Update refinery to increment on conflict
- Update priority function to read retry_count


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


towers-of-hanoi-10

AGENT EXECUTION PROTOCOL - Towers of Hanoi (10 disks, 1023 moves)

PURPOSE: This is a durability proof, not computation. Steps are pre-computed.
Your job is to execute them mechanically, proving crash-recovery at scale.

EXECUTION LOOP:
1. Find current state: bd mol current <mol-id>
2. Find the next ready (unblocked) step
3. Close it: bd close <step-id>
4. Repeat until no ready steps remain

ON RESUME (after crash/restart/handoff):
- Same as fresh start. The molecule IS the state.
- Query `bd mol current <mol-id>`, continue from there.
- No memory of previous session needed.

DO:
- Close steps as fast as possible (they're trivial mechanical moves)
- Use `gt handoff` when context fills (proactive cycling)
- Trust the pre-computed solution - every move is already correct

DO NOT:
- Try to solve Hanoi yourself - moves are already computed
- Mark steps in_progress - just close them directly
- Ask for permission - this is GUPP territory, just execute
- Stop for human input - run autonomously until complete

MONITORING:
- Progress: Count closed children of the molecule
- For mega-molecules: Use convoy dashboard when available
- Completion: All steps closed = molecule complete

This proves Gas Town can execute arbitrarily long workflows with
nondeterministic idempotence - different sessions, same outcome.


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 373/1023)


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 681/1023)


Digest: mol-deacon-patrol

Cycle 188: Nominal


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 775/1023)


gt sling: use mail queue for patrol roles (witness, refinery, deacon)

When slinging work to patrol agents, queue via mail instead of replacing hook.

**Rationale:**
Patrol agents run continuous loops. Replacing their hook with discrete work breaks patrol continuity - when the task completes, the patrol stops.

**New behavior for patrol roles (witness, refinery, deacon):**
1. Check if patrol is running (hook has patrol molecule attached)
2. If patrol running:
   - Don't touch hook (patrol stays pinned)
   - Send work assignment mail
   - Print 'Queued for next patrol cycle'
3. If patrol NOT running:
   - Start default patrol for that role (mol-witness-patrol, mol-refinery-patrol, mol-deacon-patrol)
   - Send work assignment mail
   - Print 'Started patrol and queued work'

**New flags:**
- --urgent: Interrupt current patrol cycle, process this work immediately
- --replace: Explicitly terminate patrol and pin discrete work (break-glass)

**No change for:**
- Polecat, Crew, Mayor (discrete task agents - current behavior)

**Dependencies:**
- Patrol templates must have 'check inbox' step (verify/add)
- Need to know default patrol molecule for each role


Daemon must delete LIFECYCLE messages after processing

## Problem

Crew workers were being killed every 5 minutes.

## Root Cause

Old stale LIFECYCLE messages from days ago were sitting in the deacon's inbox. The daemon's ProcessLifecycleRequests() was re-finding and re-processing them every 5-minute heartbeat cycle.

The closeMessage() function in lifecycle.go calls 'gt mail delete' but failures are silent - the message stays in the inbox and gets reprocessed on the next heartbeat.

## Fix Required

1. Ensure closeMessage() actually deletes the message
2. If delete fails, log the error AND mark the message as read so it's not reprocessed
3. Consider adding a 'processed' label or moving to a processed folder

## Files

- internal/daemon/lifecycle.go: closeMessage() function
- internal/daemon/lifecycle.go: ProcessLifecycleRequests() loop


Merge: gt-tnca.1

branch: polecat/immortan
target: main
source_issue: gt-tnca.1
rig: gastown


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 430/1023)


Digest: mol-deacon-patrol

Patrol cycle 24: quick check, all healthy


Digest: mol-deacon-patrol

Patrol 10 complete


Digest: mol-deacon-patrol

Patrol #18: Quick cycle, all quiet.


Digest: mol-deacon-patrol

Patrol 18: Green


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.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


test pin fix 2


bd sync: Handle mol-* prefix for protos gracefully

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

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

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

Related: bd-47qx


Digest: mol-deacon-patrol

Patrol 13: 3 rigs healthy


Digest: mol-deacon-patrol

P15: stable


Merge: rictus-mjtlq9xg

branch: polecat/rictus-mjtlq9xg
target: main
source_issue: rictus-mjtlq9xg
rig: gastown


Digest: mol-deacon-patrol

Patrol 13: All healthy, no messages


Polecat template: remove redundant 'Finding Work' section

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


Delete molecules_*.go files

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

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


gt done fails in worktree: missing remote.origin.fetch config


Merge: cheedo-1767146245543

branch: polecat/cheedo-1767146245543
target: main
source_issue: cheedo-1767146245543
rig: gastown


mol-polecat-work minimal formula

Create minimal mol-polecat-work formula for tracer bullet.

## Simplified Steps

For v0.1, just the essentials:

```yaml
formula: mol-polecat-work-v01
description: Minimal polecat work cycle for tracer bullet.
version: 1

variables:
  - name: issue_id
    required: true
  - name: rig
    required: true

steps:
  - id: claim
    title: Claim the issue
    description: |
      Run: bd update {{issue_id}} --status=in_progress
      Read the issue: bd show {{issue_id}}
      Understand what needs to be done.

  - id: work
    title: Implement the fix
    needs: [claim]
    description: |
      Do the work described in the issue.
      Make your changes.
      Test them.
      Commit with issue ID: git commit -m "description ({{issue_id}})"

  - id: submit
    title: Submit for review
    needs: [work]
    description: |
      Push your branch: git push -u origin <branch>
      Create MR: bd create "Merge: {{issue_id}}" --type=merge-request
      Close issue: bd close {{issue_id}}
      Sync: bd sync
      Signal done: gt mail send witness/ -s "LIFECYCLE: Done"
```

## Location

.beads/formulas/mol-polecat-work-v01.formula.yaml

## Notes

- Keep it simple for tracer bullet
- Full mol-polecat-work can be more elaborate
- This proves the pattern works


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


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 715/1023)


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 358/1023)


Digest: mol-deacon-patrol

Patrol 20: all healthy


Digest: mol-deacon-patrol

Patrol cycle 2: all monitors healthy, 1 dog idle, no incidents


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 507/1023)


Digest: mol-deacon-patrol

Patrol cycle 7: all nominal


mol-deacon-patrol


🤝 HANDOFF: Timing fixes applied

Fixed mayor attach timing bug. Completed: timing fix, gt-tulx, Emma beads-6v2. Remaining P1: gt-17zr, gt-kcee, gt-szsq. Run gt prime on startup.


test message


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 725/1023)


Move disk 4: C → B

Move disk 4 from peg C to peg B. (Move 744/1023)


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 198/1023)


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 77/1023)


Move disk 4: A → C

Move disk 4 from peg A to peg C. (Move 776/1023)


gt orphans: Find lost polecat work

Add a command to find orphaned commits that were never merged to main.

## Problem
Polecat work can get lost when:
- Session killed before merge
- Refinery fails to process
- Network issues during push

## Solution
Add `gt orphans` command that:
1. Uses `git fsck --unreachable` to find dangling commits
2. Filters to recent commits (default: 7 days, configurable)
3. Excludes stash/index entries (WIP on, index on)
4. Shows commit details and suggests recovery

## Usage
```
gt orphans              # Last 7 days
gt orphans --days=14    # Last 2 weeks
gt orphans --recover    # Interactive cherry-pick
```

## Found orphans (Dec 16-20, 2025)
- 3b146c11: Fix mail read auto-ack and add Mayor startup directive
- b6fdc561: Add persistent theme config and fix crew session theming
- 97aba756: Unify gt prime to call bd prime and mail check
- ce769ca5: Add mol-bootstrap molecule for Gas Town installation
- b2219de7: Add bootstrap documentation for new Gas Town installations
- bc82348: feat: Add gt done command (already recovered)


Implement await type handlers (gh:run, gh:pr, timer, human, mail)

Implement condition checking for each await type.

## Handlers Needed
- gh:run:<id> - Check GitHub Actions run status via gh CLI
- gh:pr:<id> - Check PR merged/closed status via gh CLI
- timer:<duration> - Simple elapsed time check
- human:<prompt> - Check for human approval (via mail?)
- mail:<pattern> - Check for mail matching pattern

## Interface
```go
type AwaitHandler interface {
    Check(awaitID string) (completed bool, result string, err error)
}
```

## Moved from beads
Originally bd-2l03. Deacon handlers belong in gastown.


Check convoy completion

Check convoy completion status.

Convoys are coordination beads that track multiple issues across rigs. When all tracked issues close, the convoy auto-closes.

**Step 1: Find open convoys**
```bash
bd list --type=convoy --status=open
```

**Step 2: For each open convoy, check tracked issues**
```bash
bd show <convoy-id>
# Look for 'tracks' or 'dependencies' field listing tracked issues
```

**Step 3: If all tracked issues are closed, close the convoy**
```bash
# Check each tracked issue
for issue in tracked_issues:
    bd show <issue-id>
    # If status is open/in_progress, convoy stays open
    # If all are closed (completed, wontfix, etc.), convoy is complete

# Close convoy when all tracked issues are done
bd close <convoy-id> --reason "All tracked issues completed"
```

**Note**: Convoys support cross-prefix tracking (e.g., hq-* convoy can track gt-*, bd-* issues). Use full IDs when checking.


Digest: mol-deacon-patrol

Patrol cycle 48: All healthy


Fix namepool Save() to use write lock

attached_args: Fix namepool Save() mutex for thread safety

Fix incorrect mutex usage in namepool Save() method.

## Files to modify
- internal/polecat/namepool.go

## Problem (lines 179-194)
Save() uses RLock() but performs file I/O:
```go
func (p *NamePool) Save() error {
    p.mu.RLock()  // WRONG: file write needs write lock
    defer p.mu.RUnlock()
    // ... file operations ...
}
```

## Fix
Change to write lock:
```go
func (p *NamePool) Save() error {
    p.mu.Lock()
    defer p.mu.Unlock()
    // ... file operations ...
}
```

## Acceptance criteria
- [ ] Save() uses Lock() instead of RLock()
- [ ] go test -race ./internal/polecat/... passes
- [ ] Existing namepool tests still pass


Digest: mol-deacon-patrol

Patrol 147: All healthy, 2 polecats working


Digest: mol-deacon-patrol

Patrol 4: Stable


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.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Digest: mol-deacon-patrol

Patrol 218: All nominal


mol-deacon-patrol


End-to-end integration test

Create and run end-to-end integration test.

## Test Scenario

1. Clean state: no polecats, fresh beads
2. Create test issue: simple documentation fix
3. Verify Deacon sees it: bd ready shows issue
4. Trigger Deacon: send heartbeat or wait
5. Verify spawn: gt polecats shows new polecat
6. Watch polecat work: tmux attach
7. Verify completion: issue closed, MR created

## Test Script

```bash
#!/bin/bash
# e2e-test.sh

# 1. Clean state
gt polecat remove --all
bd create "Test: update README typo" --type=task --priority=1

# 2. Verify ready
bd ready | grep "update README"

# 3. Wait for Deacon or trigger
# (manual for v0.1)

# 4. Watch
gt status
gt polecats gastown

# 5. Wait for completion
# (manual observation for v0.1)

# 6. Verify
bd list --status=closed | grep "update README"
```

## Success Criteria

- Issue created and visible in bd ready
- Polecat spawned and working
- Issue closed with commit reference
- No manual intervention (except observation)


Digest: mol-deacon-patrol

Patrol 15: All healthy.


Witness: Verify MR submission on notification

When Witness receives `LIFECYCLE: mr submitted`, verify the submission was clean.

## Implementation

1. Add handler for "LIFECYCLE: mr submitted" mail
2. Check MR status: `gt mq status <mr-id>`
3. If MR looks good (status=open, no errors): log success, allow polecat to idle
4. If MR has issues:
   - Check polecat git state
   - Nudge polecat to fix if session still alive
   - Log issue for monitoring

## Acceptance
- Witness verifies MR after submission notification
- Can detect problematic submissions
- Provides early intervention opportunity


Digest: mol-deacon-patrol

Patrol 4: routine, all healthy


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

Patrol 14


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 953/1023)


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 930/1023)


Audit hardcoded 'gastown' references in codebase

## Problem

Gas Town should work for ANY rig - not assume 'gastown' (our OSS project) is installed. Found during audit:

### Known Issue (Closed - gt-ci84)
- Deacon patrol wisps were incorrectly using `gastown/mayor/rig/.beads/` instead of town-level beads
- Status: Fixed (implemented town-level wisp storage)

### Remaining Issues

1. **log.go:272** - Fallback path heuristic:
   ```go
   possibleRoots := []string{
       home + "/gt",
       home + "/gastown",  // <-- Assumes user might have gastown as town
   }
   ```
   Should be removed or use a config-based approach.

2. **Help text examples** - Many commands use 'gastown' as the example rig:
   - `gt sling gt-abc gastown`
   - `gt witness start gastown`
   - etc.
   Consider using a generic name like 'myproject' or '<rig>'

3. **Polecat name pool** - 'gastown' is in the Mad Max themed name list.
   This is acceptable (just a name, not a path assumption).

## Tasks
1. Remove `home + "/gastown"` fallback from log.go
2. Consider updating help examples to use generic rig names
3. Full code audit to ensure no other hardcoded assumptions

## Context
Gas Town is the orchestration framework. 'gastown' is just our OSS project that happens to use it. Users installing Gas Town for their own projects should never see anything that assumes 'gastown' rig exists.


Consider splitting large files (800+ lines)

Several files are getting large and may benefit from splitting:
- internal/beads/beads.go (990 lines)
- internal/cmd/molecule.go (981 lines)
- internal/refinery/manager.go (934 lines)
- internal/beads/beads_test.go (883 lines)
- internal/cmd/polecat.go (836 lines)
- internal/witness/manager.go (808 lines)
- internal/cmd/mail.go (804 lines)

For .go files, consider extracting logical subsystems. For test files, this is lower priority.


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 921/1023)


Digest: mol-deacon-patrol

Cycle 183: All agents healthy, no incidents


Execute registered plugins

Execute registered plugins.

Scan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with TOML 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.


Day 4.5: Test multi-step molecule lifecycle

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

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

Parent: gt-4a2qt


Design Convoy formula

## Design Convoy Formula

Structured design exploration for features/architecture.

### Input
- Problem statement or feature request

### Legs (parallel polecats)
| Leg | Focus | Output |
|-----|-------|--------|
| api | Interface design, ergonomics | api-design.md |
| data | Data model, storage, migrations | data-model.md |
| ux | User experience, CLI ergonomics | ux-analysis.md |
| scale | Performance at scale, bottlenecks | scalability.md |
| security | Threat model, attack surface | security.md |
| integration | How it fits existing system | integration.md |

### Synthesis
- Read all dimension analyses
- Identify conflicts and tradeoffs
- Propose unified design with options
- Flag decisions needing human input

### Command
```bash
gt formula run design --problem="Add notification levels to mayor"
# Creates design convoy
# Spawns dimension polecats
# Lands with design-doc.md
```


Digest: mol-deacon-patrol

Patrol 9: 3 rigs healthy


Migrate startup paths from SessionBeacon to StartupNudge

## Problem
StartupNudge function exists (gt-bgfqy) but no code uses it.
All startup paths still call session.SessionBeacon() + 'gt prime' separately.

SessionBeacon format: [GAS TOWN] address • molID • timestamp
StartupNudge format: [GAS TOWN] recipient <- sender • timestamp • topic

The key difference is SENDER - needed for seance discovery ('who started this session?').

## Files to Update
- internal/cmd/crew_lifecycle.go (lines 354-371, 525-538)
- internal/cmd/start.go (lines 757, 805-810, 946-949)
- internal/cmd/deacon.go (line 307)
- internal/cmd/witness.go (line 350)
- internal/cmd/up.go (lines 288, 335, 559, 660)
- internal/cmd/mayor.go (line 151)
- internal/session/manager.go (lines 205, 215)

## Pattern
Replace:
  beacon := session.SessionBeacon(address, molID)
  t.NudgeSession(sessionID, beacon)
  t.NudgeSession(sessionID, "gt prime")

With:
  cfg := session.StartupNudgeConfig{Recipient: address, Sender: sender, Topic: topic, MolID: molID}
  session.StartupNudge(t, sessionID, cfg)
  // Note: StartupNudge is the session title, still need separate 'gt prime' for priming

## Related
- gt-85whr (parent epic)
- gt-j0546 (did RuntimeConfig refactor, not StartupNudge)


Session ended: gt-gastown-nux


Digest: mol-deacon-patrol

Patrol 7: healthy


Speed up test suite

Tests are running slow during MQ processing. Investigate and optimize:
- Profile test execution time
- Look for slow tests (network, file I/O, sleeps)
- Consider parallel test execution
- Cache expensive setup where possible


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 259/1023)


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 366/1023)


Digest: mol-deacon-patrol

Patrol 104: All agents healthy, no incidents


Digest: mol-deacon-patrol

Patrol cycle 1: All rigs healthy, no incidents


gt commands should follow .beads/redirect

## Problem

`gt sling` (and likely other gt commands) don't follow the `.beads/redirect` file that `bd` uses to share beads across clones.

This caused confusion during the v0.39.0 release: molecules were poured successfully to mayor/rig's beads (via redirect), but `gt sling` couldn't find them because it was looking in the crew clone's local .beads/.

## Expected Behavior

All `gt` commands that interact with beads should follow the redirect mechanism that `bd` uses.

## Affected Commands (likely)

- `gt sling`
- `gt hook`
- `gt mol status`
- `gt mol attach`
- Any command that shells out to `bd show` or similar

## Solution

When `gt` needs to find the beads directory, check for `.beads/redirect` and follow it, same as `bd` does.


Add workspace metadata file (.town.json)

Create ~/gt/.town.json with owner email, workspace name, and public name. Anchors workspace to entity identity for federation.


Merge: dementus-1767073385126

branch: polecat/dementus-1767073385126
target: main
source_issue: dementus-1767073385126
rig: gastown


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.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Merge: gt-70b3

type: merge-request
branch: polecat/Rictus
target: main
source_issue: gt-70b3
rig: gastown


Move disk 3: B → C

Move disk 3 from peg B to peg C. (Move 1020/1023)


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.


test-new-swarm-1767338498


Move disk 2: A → C

Move disk 2 from peg A to peg C. (Move 806/1023)


Merge: cheedo-mjw70xce

branch: polecat/cheedo-mjw70xce
target: main
source_issue: cheedo-mjw70xce
rig: gastown
agent_bead: gt-gastown-polecat-cheedo


Digest: mol-deacon-patrol

Patrol 2: Routine, all healthy


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 942/1023)


Runtime dynamic expansion (for-each)

Implement runtime expansion for discovered work (the for-each construct).

## Syntax

    step: survey-workers
    on-complete:
      for-each: output.polecats
      bond: mol-polecat-arm
      vars:
        polecat_name: "{item.name}"
        rig: "{item.rig}"
      parallel: true  # or sequential: true

## Design Context (from gt-8tmz.4 review)

This is **control flow**, not just expansion. It affects execution order:
- for-each with parallel: true = concurrent child execution
- for-each with sequential: true = ordered child execution

Key patrol patterns that require this:

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

## Relationship to gt-8tmz.4

gt-8tmz.4 implements loop, gate, branch (static control flow).
This issue implements for-each (dynamic control flow over runtime-discovered collections).

Together they cover the full control flow needs for patrol formulas.

## Implementation Notes

- Bonds N instances based on step output
- Christmas Ornament pattern: fanout from single step to N parallel children
- Pairs with waits-for gate (gt-8tmz.38) for aggregation
- Collection must be iterable (array in step output)
- Each iteration gets item, index, and parent context in vars


Feed daemon: curate raw events into user-facing feed

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

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

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

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

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

Part of epic gt-u7dxq


Digest: mol-deacon-patrol

Patrol 9: healthy


Refinery background daemon mode

The refinery 'gt refinery start' command only works in foreground mode (--foreground). Need to implement background daemon mode for production use.

Options:
1. Use a separate tmux session for the refinery
2. Implement proper daemonization
3. Use Claude Code session for the refinery agent

For MVP, option 1 (tmux session) is probably simplest.


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 321/1023)


mol-deacon-patrol

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

Original description:
Deacon patrol molecule template. Label: template


Digest: mol-deacon-patrol

Patrol 17: all clear


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 634/1023)


Add tmux hotkey (C-b f) for gt feed window

## Goal

Add a tmux hotkey (e.g., C-b f) that jumps to the activity feed window, creating it if it doesn't exist.

## Behavior

1. If 'feed' window exists in current session → switch to it
2. If 'feed' window doesn't exist → create it with `bd activity --follow`, then switch

## Implementation

Add to gt's tmux session configuration (similar to SetCrewCycleBindings):

```go
// C-b f → jump to feed window
tmux bind-key -T prefix f run-shell "gt feed --window"
```

The `gt feed --window` command already handles:
- Creating the window if missing
- Switching to it if exists
- Running `bd activity --follow` in the window

## Where to add

- `internal/tmux/tmux.go` - add SetFeedBinding() method
- Call it from session configuration (ConfigureGasTownSession or similar)

## Testing

1. In tmux: C-b f should open/switch to feed window
2. Feed window should show streaming activity
3. C-b n/p should still work to cycle back to other windows


Digest: mol-deacon-patrol

Patrol cycle 3: all healthy, no incidents


Serialized conflict resolution via merge-slot gate

## Problem: Monkey Knife Fight

Multiple conflict-resolution polecats racing to land creates cascading conflicts:
- Polecat A rebases on main@v1, resolving...
- Polecat B rebases on main@v1, resolving...
- Polecat A pushes → main@v2
- Polecat B pushes → CONFLICT (main moved) → needs re-resolve

This wastes cycles and creates thrashing.

## Solution: Merge-Slot Gate

A single merge slot per rig, implemented via gates:

```
┌─────────────────────────────────────────────────────┐
│              MERGE SLOT (gt-merge-slot)             │
│            Only one holder at a time                │
└─────────────────────────────────────────────────────┘
                         │
         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
    [High-prio MR]  [Med-prio MR]   [Low-prio MR]
     acquires slot   waits on gate   waits on gate
```

## Design

### Merge Slot Bead
Each rig has a persistent slot bead: `gt-merge-slot` (type=slot)
- Status: open (slot available) or in_progress (slot held)
- Holder field: which polecat/MR currently holds it

### Acquiring the Slot
1. Conflict polecat checks `bd show gt-merge-slot`
2. If status=open:
   - `bd update gt-merge-slot --status=in_progress --holder=<mr-id>`
   - Proceed with conflict resolution
3. If status=in_progress:
   - Create bead-gate waiting for slot to become open
   - Block until gate closes

### Priority Ordering
Convoy graph provides priority:
- Convoy age (older = higher priority)
- Epic priority (P0 > P4)
- Retry count (high retries = penalty)

Witness dispatches conflict resolution in priority order.
Only highest-priority waiting work acquires slot when released.

### Releasing the Slot
After merge to main:
1. `bd update gt-merge-slot --status=open --holder=""`
2. All waiting gates check slot
3. Highest-priority waiter acquires

### Direct-to-Main Flow
Conflict polecat with slot:
1. Rebase on main, resolve conflicts
2. Run tests
3. Push directly to main (not back to MR queue)
4. Close original MR bead
5. Release merge slot

## Benefits
- No monkey knife fight (serialized)
- Priority respected (convoy back-pressure)
- No queue re-entry (direct to main)
- Uses existing gates infrastructure

## Implementation Tasks
1. Create merge-slot bead type
2. Slot acquire/release in gt done
3. Witness priority-ordered dispatch
4. Gate-based waiting for slot

## Related
- gt-si8rq.5: Conflict resolution workflow (update to use slot)
- gt-si8rq.6: Priority-ordered MQ (provides priority info)
- bd-quw1: Phase handoff (gate infrastructure)


Merge: nux-mjtj9d8q

branch: polecat/nux-mjtj9d8q
target: main
source_issue: nux-mjtj9d8q
rig: gastown


Digest: mol-deacon-patrol

Patrol 102: All agents healthy, no incidents


Merge: capable-1767079826600

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


Digest: mol-deacon-patrol

Patrol 157: All healthy


Digest: mol-deacon-patrol

Patrol 1: All healthy. 3 rigs, 6 agents pinged. No incidents.


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.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Merge: gt-cehl8

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


Merge: dementus-mjxemx4j

branch: polecat/dementus-mjxemx4j
target: main
source_issue: dementus-mjxemx4j
rig: gastown
agent_bead: gt-gastown-polecat-dementus
Note: Session stopped without DONE - Witness cleanup


Digest: mol-deacon-patrol

Patrol 15: quick pass


Move disk 3: C → A

Move disk 3 from peg C to peg A. (Move 20/1023)


Digest: mol-deacon-patrol

Patrol 6: All clear


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 843/1023)


Meta-formulas: formula generators

Support meta-formulas that generate multiple formulas from a template. Example: multi-lang-shiny that generates shiny-go, shiny-python, shiny-typescript from a for-each loop over languages. Enables DRY formula libraries.


Digest: mol-deacon-patrol

Patrol 109: All healthy


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 322/1023)


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.


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 562/1023)


ensure-gastown-witness

Start the gastown rig Witness.

## Action
```bash
gt witness start gastown
```

## Verify
1. Session exists: `tmux has-session -t gastown-witness 2>/dev/null`
2. Not stalled: `gt peek gastown/witness` does NOT show "> Try" prompt
3. Heartbeat fresh: Last patrol cycle < 5 min ago

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

## OnFail
Log error. Rig polecats will be unmonitored until Witness recovers.


Digest: mol-deacon-patrol

Patrol OK: 0 mail, all agents healthy, 3 polecats working


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 531/1023)


Load context

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

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


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 417/1023)


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 869/1023)


Digest: mol-deacon-patrol

Patrol 16: clear


Polecat cleanup should refuse to lose uncommitted work

The system should stubbornly refuse to lose work from a polecat.

## Current Problem

- gt spawn --force bypasses safety checks
- gt shutdown doesn't check for uncommitted work
- Witness cleanup doesn't check git status

## Desired Behavior

Before any polecat cleanup, check:
1. git status - any uncommitted changes?
2. git stash list - any stashes?
3. Unpushed commits on branch?
4. Unsynced beads changes?

If ANY of these exist:
- REFUSE to clean up
- Print clear error message listing what would be lost
- Require explicit --nuclear flag to force (not just --force)

## Implementation

Add to cleanupPolecat() in witness/manager.go:
```go
func (m *Manager) checkUncommittedWork(polecatName string) error {
    dir := m.polecatDir(polecatName)

    // Check git status
    if hasUncommitted, _ := git.HasUncommittedChanges(dir); hasUncommitted {
        return fmt.Errorf("polecat %s has uncommitted changes", polecatName)
    }

    // Check stashes
    if stashCount, _ := git.StashCount(dir); stashCount > 0 {
        return fmt.Errorf("polecat %s has %d stashes", polecatName, stashCount)
    }

    // Check unpushed commits
    if unpushed, _ := git.UnpushedCommits(dir); unpushed > 0 {
        return fmt.Errorf("polecat %s has %d unpushed commits", polecatName, unpushed)
    }

    return nil
}
```

## Affected Commands

- gt shutdown
- gt rig shutdown
- Witness cleanup
- gt spawn --force (should warn if overwriting)


Update Mayor prompting in gastown-py

The Mayor CLAUDE.md and related prompting in gastown-py (still in production use) needs to reflect current design decisions: session cycling, handoff protocol, cleanup responsibilities, beads access model. Sync prompting with GGT design work.


Digest: mol-deacon-patrol

Patrol cycle 12: All healthy


Digest: mol-deacon-patrol

Patrol 256 complete: no incidents


Digest: mol-deacon-patrol

Patrol cycle 18


Digest: mol-deacon-patrol

Patrol 30: all quiet


Merge: rictus-mjw3nj1a

branch: polecat/rictus-mjw3nj1a
target: main
source_issue: rictus-mjw3nj1a
rig: gastown
agent_bead: gt-gastown-polecat-rictus


Digest: mol-deacon-patrol

Patrol #13


Digest: mol-deacon-patrol

Patrol 6: Quiet


Phase 5: Integration and Demo

$(cat /tmp/phase5.md)


Merge: dementus-1767140140908

branch: polecat/dementus-1767140140908
target: main
source_issue: dementus-1767140140908
rig: gastown


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.


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.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Design: Swarm shutdown and worker cleanup

Design for graceful swarm shutdown, worker cleanup, and session cycling.

## Key Decisions

1. Pre-kill verification uses model intelligence (not framework rules)
2. Witness can request restart when context filling (mail self, exit)
3. Mayor NOT involved in per-worker cleanup (Witness responsibility)
4. Clear responsibility boundaries between Mayor/Witness/Polecat

## Subtasks (implementation)

- gt-sd6: Polecat decommission checklist prompting
- gt-f8v: Witness pre-kill verification protocol
- gt-eu9: Witness session cycling and handoff
- gt-gl2: Mayor vs Witness cleanup responsibilities

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


Move disk 4: C → B

Move disk 4 from peg C to peg B. (Move 120/1023)


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 137/1023)


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 853/1023)


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol cycle 10


Detect cleanup needs

**DETECT ONLY** - Check if cleanup is needed and dispatch to dog.

**Step 1: Preview cleanup needs**
```bash
gt doctor -v
# Check output for issues that need cleaning
```

**Step 2: If cleanup needed, dispatch to dog**
```bash
# Sling session-gc formula to an idle dog
gt sling mol-session-gc deacon/dogs --var mode=conservative
```

**Important:** Do NOT run `gt doctor --fix` inline. Dogs handle cleanup.
The Deacon stays lightweight - detection only.

**Step 3: If nothing to clean**
Skip dispatch - system is healthy.

**Cleanup types (for reference):**
- orphan-sessions: Dead tmux sessions
- orphan-processes: Orphaned Claude processes
- wisp-gc: Old wisps past retention

**Exit criteria:** Session GC dispatched to dog (if needed).


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 1019/1023)


Move disk 5: B → C

Move disk 5 from peg B to peg C. (Move 624/1023)


Standardize agent bead naming: prefix-rig-role-name

## The Problem

Agent bead IDs use INCONSISTENT naming patterns:

| Current (WRONG) | Should Be (prefix-rig-role-name) |
|-----------------|----------------------------------|
| gt-witness-gastown | gt-gastown-witness |
| gt-refinery-gastown | gt-gastown-refinery |
| gt-crew-gastown-max | gt-gastown-crew-max |
| gt-polecat-gastown-Toast | gt-gastown-polecat-Toast |

Town-level agents (no rig) are OK:
- gt-mayor ✓
- gt-deacon ✓

## The Convention

```
prefix-rig-role-name

Where:
- prefix: always 'gt'
- rig: rig name (absent for town-level agents)
- role: witness|refinery|crew|polecat|mayor|deacon
- name: agent name (absent for singleton roles like witness/refinery)
```

Examples:
- `gt-gastown-witness` (rig=gastown, role=witness, no name)
- `gt-gastown-crew-max` (rig=gastown, role=crew, name=max)
- `gt-beads-polecat-Toast` (rig=beads, role=polecat, name=Toast)
- `gt-mayor` (no rig, role=mayor, no name)

## Files to Update

### Agent bead ID generation
- internal/cmd/status.go (lines 316-335)
- internal/daemon/lifecycle.go (lines 546-579)
- internal/cmd/crew_add.go
- internal/polecat/manager.go
- internal/rig/manager.go
- internal/doctor/agent_beads_check.go
- internal/cmd/prime.go
- internal/session/names.go (session names vs bead IDs)

### Commands to verify
- gt status - displays agent beads
- gt doctor - creates missing agent beads
- gt rig add - creates witness/refinery beads
- gt crew add - creates crew beads
- gt sling - routes by agent ID
- gt mol status - looks up agent by ID

## Migration

1. Update all ID generation code
2. Create new agent beads with correct IDs
3. Migrate hook/role slots to new beads
4. Update any mail addresses
5. Delete old incorrectly-named beads

## Also from this session

Role bead slot cleanup was done - CreateAgentBead now calls bd slot set.
But legacy description parsing still exists in daemon/lifecycle.go.

## Reference
- ~/gt/docs/agent-as-bead.md
- Session 2025-12-29: Fixed role bead patterns (gt-crew-role etc)


Leg prompts: Template system for polecat instructions

Create leg prompt templates:
- Base template with context (PR, files, formula name)
- Leg-specific focus injection
- Output format instructions (findings.md)
- Store in .beads/formulas/prompts/ or inline in formula.toml

Ensure polecats know to write output to specific location.


Implement sendToQueue() for queue message delivery

Add queue message delivery to internal/mail/router.go.

SEMANTICS:
- Queue messages are stored in a shared location, NOT individual inboxes
- Location: {townRoot}/.beads/ with special metadata

MESSAGE METADATA:
Add to message struct or use existing fields:
- queue_name: which queue this belongs to
- claimed_by: empty until claimed
- claimed_at: timestamp when claimed

IMPLEMENTATION:
1. Add sendToQueue(msg *Message) error
2. Validate sender is eligible (optional, or allow anyone to post)
3. Create message bead with queue_name in metadata
4. Message To field should be 'queue:{name}'

FILE: internal/mail/router.go
PATTERN: Follow sendToList() at line 567 but create ONE copy, not fan-out

Do not implement claim/release yet - just delivery.


Synthesis: Combine leg outputs into final deliverable

Implement synthesis step:
1. Collect all leg outputs (findings.md files)
2. Spawn synthesis polecat with combined context
3. Synthesis prompt: dedupe, prioritize, format
4. Output: review-summary.md attached to convoy bead
5. Close convoy when synthesis complete

Consider: bd slot or bd attach for outputs.


Digest: mol-deacon-patrol

Cycle 14


Move disk 4: B → A

Move disk 4 from peg B to peg A. (Move 952/1023)


Digest: mol-deacon-patrol

Patrol 8: All healthy, no messages


Instrument gt commands to appear in activity feed

## Architecture: Two-tier event system

```
┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│ gt commands │  │ bd mutations│  │ agent output│
└──────┬──────┘  └──────┬──────┘  └──────┬──────┘
       └────────────────┼────────────────┘
                        ▼
              ~/gt/.events.jsonl (raw, audit)
                        │
              ┌─────────────────┐
              │  Feed daemon    │ ← goroutine in gt daemon
              │  - filters      │
              │  - aggregates   │
              │  - AI curates   │
              └────────┬────────┘
                       ▼
              ~/gt/.feed.jsonl (curated, user-facing)
```

## Event format

```json
{
  "ts": "2025-12-28T10:30:15Z",
  "source": "gt",
  "type": "sling",
  "actor": "mayor",
  "payload": {"bead": "gt-xyz", "target": "gastown/Toast"},
  "visibility": "feed"
}
```

Visibility: `audit` | `feed` | `both`

## Implementation phases

1. **Event logging** - gt commands write to ~/gt/.events.jsonl
2. **Feed daemon** - goroutine in gt daemon tails events, writes curated feed
3. **Feed readers** - gt feed, gt dashboard read from .feed.jsonl
4. **AI curation** - future: haiku summarization for complex activity

Part of epic gt-u7dxq


Merge: dag-mjw70jg8

branch: polecat/dag-mjw70jg8
target: main
source_issue: dag-mjw70jg8
rig: gastown
agent_bead: gt-gastown-polecat-dag


load-context

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

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


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 913/1023)