Move disk 1: B → C

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


CLI: doctor diagnostics and auto-repair

GGT completely lacks the doctor command which is critical for debugging.

Required Commands:
- gt doctor [<rig>] - Run diagnostic checks
- gt doctor --fix - Auto-repair common issues

Checks to Implement:
Workspace Level: Config validity, Mayor mailbox, Rig registry
Rig Level: Git state, clone health, witness/refinery presence, beads sync
Swarm Level: Stuck detection, zombie sessions, heartbeat health

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


Merge: gt-o3is

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


Move disk 2: B → A

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


Digest: mol-deacon-patrol

Patrol 32: all quiet


Update Deacon template to emphasize staying in ~/gt/deacon directory

The Deacon template should instruct the agent to stay in ~/gt/deacon/ as much as possible, and always return there after any excursion. This prevents issues with identity detection (mail, mol status) which depend on cwd.


Move disk 3: A → B

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


Digest: mol-deacon-patrol

Patrol 17: Mayor OK, 11 sessions


mol-witness-patrol

Per-rig worker monitor patrol loop.

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

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

This molecule uses wisp storage (.beads-wisp/) for ephemeral patrol state.
Persistent state (nudge counts, handoffs) is stored in a witness handoff bead.


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.


Session ended: gt-gastown-organic


Merge: capable-1767146233256

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


Digest: mol-deacon-patrol

Patrol 242 complete: 6 polecats active; 3 witnesses, 3 refineries healthy; 1 dog idle; no incidents


gt polecat add should spawn with --dangerously-skip-permissions

When adding polecats via gt polecat add, the subsequent Claude session needs --dangerously-skip-permissions flag to run autonomously.

Currently:
- gt polecat add creates worktree
- tmux new-session spawns 'claude' without flags
- Polecat gets stuck at permission prompts

Needed:
- gt polecat add (or gt sling) should spawn with --dangerously-skip-permissions
- Or store a config in polecat worktree indicating autonomous mode

This is critical for swarm automation - polecats can't self-approve permissions.


Digest: mol-deacon-patrol

Patrol cycle 19: All healthy


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 17: All healthy.


Create internal/tui/ package with feed model

Create the TUI infrastructure for gt feed.

## Package structure
```
internal/tui/
  feed/
    model.go       # bubbletea Model struct
    view.go        # View() rendering
    update.go      # Update() message handling
    events.go      # Event stream subscription (tail .feed.jsonl)
    styles.go      # lipgloss styles
    keys.go        # Key bindings
```

## Model components
1. **AgentTree** - Collapsible tree of agents by role
2. **EventStream** - Scrollable viewport of recent events
3. **StatusBar** - Current filter, help hints
4. **FilterPopup** - Modal for setting filters

## Key bindings
- j/k - scroll events
- J/K - scroll agent tree
- tab - switch focus (tree/stream)
- enter - expand/details
- / - search
- f - filter popup
- q - quit
- ? - help

## Event subscription
- Tail ~/gt/.feed.jsonl using fsnotify or polling
- Parse JSONL events
- Send as bubbletea messages to update model


Day 2.3: Agent writes state on lifecycle events

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

State is self-reported, not inferred.

Implementation: Wire up agent lifecycle hooks (SessionStart, SessionEnd, health checks) to call bd agent state.

Parent: gt-d0jqp


Merge: gt-h6eq.3

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


Work assignment mail not received by polecat

When gt spawn sends a work assignment:

1. gt spawn says '✓ Work assignment sent'
2. Polecat runs 'gt mail inbox'
3. Shows '0 messages, 0 unread'

The work assignment mail never arrived at the polecat's inbox.

## Observed in session
- Spawned polecat dementus on gt-th7
- Polecat checked inbox: empty
- Polecat couldn't find issue (separate sync bug)

## Possible causes
- Mail routing issue for polecat addresses
- gt spawn not actually sending mail
- Mail sent to wrong address format

This was likely caused by stale beads in old polecats. With gt-9nf (fresh polecats), polecats now use shared rig beads via redirect file, eliminating sync issues. Mail routing uses town beads correctly.


Digest: mol-deacon-patrol

Patrol 4: gastown+beads witnesses/refineries healthy


Digest: mol-deacon-patrol

Patrol #15: All healthy


MQ events in gt feed

Wire MQ lifecycle events to gt feed display.

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

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


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.


Formula versioning and migration strategy

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

Deferred: post-launch polish


Digest: mol-deacon-patrol

Patrol 219: All nominal


Day 1.5: Create role beads from CLAUDE.md content

Create role beads from existing CLAUDE.md files:
- gt-mayor-role (from mayor CLAUDE.md)
- gt-witness-role (from witness CLAUDE.md)
- gt-refinery-role (from refinery CLAUDE.md)

Each role bead contains priming instructions and default_molecule.

Parent: gt-d0jqp


Move disk 3: C → A

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 3: All healthy, quiet


Digest: mol-deacon-patrol

Patrol cycle 17


Digest: mol-deacon-patrol

Patrol cycle 8: all nominal


Merge: slit-1767075898886

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


Digest: mol-deacon-patrol

Patrol cycle 21: All 3 witnesses and refineries healthy, no orphans, no gates, inbox clean


Digest: mol-deacon-patrol

Patrol 77: Routine


Digest: mol-deacon-patrol

Patrol 12: all healthy


Digest: mol-deacon-patrol

Patrol complete: no callbacks, agents healthy, 1 stale lock cleaned


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

Patrol 15


gt doctor: Detect and clean up orphaned sessions/processes

## Problem
Orphaned tmux sessions and Claude processes accumulate over time, consuming memory.

## Discovered Orphans
- gt-deacon: Idle Claude session, not part of any rig

## Proposed Solution

### gt doctor --check (default)
Detect issues without fixing:
- Orphan sessions (not matching rig/polecat/crew/witness/refinery/mayor pattern)
- Claude processes without parent tmux session
- Tmux sessions without Claude (stuck at bash prompt)
- Polecats marked 'working' but session idle

### gt doctor --fix
Clean up detected issues:
- Kill orphan sessions
- Kill orphan Claude processes
- Optionally reset stuck polecat state

### gt gc (alternative name)
Short alias for cleanup operations.

## Acceptance Criteria
- [ ] Detects orphan sessions
- [ ] Detects orphan processes
- [ ] Safe cleanup (doesn't kill active work)
- [ ] Reports what was cleaned


Digest: mol-deacon-patrol

Patrol #5: Stable


Digest: mol-deacon-patrol

Patrol 29: all quiet


gt mq status: detailed MR view

Implement 'gt mq status <id>' command for detailed MR view.

Display:
- All MR fields (branch, target, source_issue, worker, rig)
- Current status with timestamps
- Dependencies (what it's waiting on)
- Blockers (what's waiting on it)
- Processing history (attempts, failures)

Under the hood: bd show <id> with MR-specific formatting.

Reference: docs/merge-queue-design.md#command-details


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 20: Final cycle, all services healthy, handoff


Molecule state file management

## Cross-Repo Reference

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

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

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


Merge: rictus-1767073382273

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


Digest: mol-deacon-patrol

Patrol 246 complete: no incidents


Digest: mol-deacon-patrol

Patrol cycle 5: All 3 rigs healthy. No incidents.


Digest: mol-deacon-patrol


Move disk 3: C → A

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


Move disk 1: A → B

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


Merge: cheedo-1767079863534

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


Digest: mol-deacon-patrol

Patrol cycle 77: All healthy


Digest: mol-deacon-patrol

Patrol cycle 2: All healthy


Digest: mol-deacon-patrol

Patrol cycle 4: All 6 agents healthy, 2 polecats, refinery queues processing


Move disk 3: B → C

Move disk 3 from peg B to peg C. (Move 708/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.

## 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 #4: All systems nominal


Digest: mol-deacon-patrol

Patrol 144: All healthy, 2 polecats working


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 20: All healthy, routine cycle complete


Move disk 1: B → C

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


Build rig/worker tree view component

Bubbletea component showing hierarchical rig list with workers. Each rig expandable to show workers. Each worker shows: status indicator, current molecule title, step progress (X/Y), time since last activity.


Digest: mol-deacon-patrol

Cycle 12: quiet


Digest: mol-deacon-patrol

Patrol cycle 19: All agents healthy


Witness handoff bead state persistence

Implement state persistence for Witness across wisp cycles.

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

## Solution
Witness handoff bead with worker_states field:

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

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

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


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol 16: all clear


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)


MQ Submit: Notify Witness on MR submission

When `gt mq submit` is run, notify the Witness so it can verify the submission.

## Implementation

1. In mq_submit.go after successful MR creation:
   ```
   gt mail send <rig>/witness -s "LIFECYCLE: mr submitted" -m "
   Worker: <polecat>
   MR: <mr-id>
   Branch: <branch-name>
   Target: <target-branch>
   Action: Verify MR submission, help polecat if needed.
   "
   ```

2. This happens BEFORE the existing polecat auto-cleanup logic

## Acceptance
- MR submission sends notification to Witness
- Witness receives mail with all relevant details
- Works for both polecat and crew submissions


gt rig status <rig> - show status for specific rig

Show detailed status for a specific rig including all workers (witness, refinery, polecats, crew).


Task A: Setup foundation


mol-deacon-patrol minimal formula

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

## Simplified Patrol (v0.1)

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

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

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

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

      ## Heuristics

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

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

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

## Loop via Reset

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

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

## Cycle via Handoff

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

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

## Location

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


Move disk 1: C → A

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


Swarm: report generation

Generate markdown reports for completed swarms.

## Command
```
gt swarm report <swarm-id> [--save <file>]
```

## Report Content

### Header
- Swarm ID and title
- Created/completed timestamps
- Duration
- Rig name

### Task Summary
| Task | Assignee | Status | Duration |
|------|----------|--------|----------|
| gt-xxx | Toast | merged | 15m |
| gt-yyy | Nux | merged | 22m |

### Worker Contributions
- Commits per worker
- Issues closed per worker
- Lines changed (optional)

### Timeline
- Chronological events from events.jsonl
- Key milestones (started, first merge, landing)

### Issues Encountered
- Conflicts resolved
- Failed tasks (if any)
- Escalations

## Implementation
```go
func GenerateReport(swarmID string) (*SwarmReport, error)
func (r *SwarmReport) ToMarkdown() string
```

## Storage
- Save to <rig>/.gastown/swarms/<id>/report.md
- Or user-specified path with --save

## PGT Reference
gastown-py/src/gastown/swarm/manager.py generate_report()

## Acceptance Criteria
- [ ] Markdown report generated
- [ ] Includes all sections above
- [ ] Auto-saved to swarm directory
- [ ] --save allows custom path


Digest: mol-deacon-patrol

Patrol 5: 3 rigs healthy


Mayor startup protocol prompting

Add startup protocol to Mayor CLAUDE.md template.

## On Session Start

1. Check for handoff:
   town inbox | grep "Session Handoff"

2. If handoff found:
   - Read it: town read <msg-id>
   - Process pending escalations (highest priority)
   - Check status of noted swarms
   - Verify rig health matches notes
   - Continue with documented next steps

3. If no handoff:
   town status     # Overall health
   town rigs       # Each rig
   bd ready        # Work items
   town inbox      # Any messages
   Build your own picture of current state.

4. After processing handoff:
   - Archive or delete the handoff message
   - You now own the current state

## Handoff Best Practices

- Be specific: 'Toast has merge conflict in auth/middleware.go' not 'Toast is stuck'
- Include context: Why decisions are pending, what you were thinking
- Prioritize next steps: What is most urgent
- Note time-sensitive items: Anything that might have changed since handoff


mol-deacon-patrol


Move disk 2: C → B

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


Digest: mol-deacon-patrol

Patrol 6: All clear


Digest: mol-deacon-patrol

Patrol 127: All healthy


check-refinery

Ensure the refinery is alive and processing merge requests.

Needs: inbox-check


gt-gastown-polecat-imperator

gt-gastown-polecat-imperator

role_type: polecat
rig: gastown
agent_state: spawning
hook_bead: null
role_bead: gt-polecat-role
cleanup_status: has_stash
active_mr: gt-usytz
notification_level: null


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 5: B → C

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


Move disk 1: C → A

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


load-context

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

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


Move disk 4: C → B

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


Digest: mol-deacon-patrol

Patrol cycle 6: All 3 rigs healthy. No incidents.


Digest: mol-deacon-patrol

Patrol 20: All healthy - handoff threshold reached


Digest: mol-deacon-patrol

Patrol 8: all healthy


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 535/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-md2rg
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Digest: mol-deacon-patrol

Patrol cycle 12: All agents healthy


Remove keepalive file infrastructure

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

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

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


Merge: nux-1767084010093

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


Digest: mol-deacon-patrol

Patrol 19: Mayor OK, 11 sessions


Move disk 1: C → A

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


Move disk 4: C → B

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


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: gt-pyqv

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


Multiple merge/landing models documented without clarification

Architecture describes three different merge models:

1. Refinery-only model (traditional)
2. Direct landing model (Mayor bypass)
3. Swarm integration branch model (internal/swarm)

These appear to conflict. Documentation should clarify:
- Which model is canonical?
- When to use which model?
- Or are some deprecated?

This is confusing for users trying to understand the system.


Digest: mol-deacon-patrol

Patrol 14: all clear


Polecat template: move startup announcement into molecule

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


Move disk 1: C → A

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


Rig doctor checks: Refinery health, clones, gitignore

Rig-level doctor checks.

## Checks

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

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

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

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

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

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

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

## Implementation

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


Move disk 1: C → A

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


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 394/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.

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


Conditional aspects (feature flags)

Apply aspects conditionally based on environment or config. Example: apply security-audit only when env.SECURITY_SCANNING == enabled. Adds 'when' clause to aspect composition.


Digest: mol-deacon-patrol

Patrol 245 complete: no incidents


Digest: mol-deacon-patrol

Patrol 38: all quiet


Witness Arm Bonding

# Witness Patrol Redesign

> **Status**: Design pivoted from Christmas Ornament to linear patrol (Dec 2024)

## Original Problem

Witness needs to monitor and intervene on multiple polecats. Original design proposed "Christmas Ornament" pattern with dynamic arms per polecat and fanout gates.

## Design Pivot: Why Christmas Ornament Was Wrong

The Christmas Ornament pattern (dynamic mol-polecat-arm per worker) felt un-Gas-Town:

1. **Explicit state tracking**: Nudge counts, timestamps, per-polecat state
2. **Complex machinery**: Dynamic bonding, fanout gates, aggregation
3. **Against philosophy**: Gas Town prefers discovery over tracking, events over state

**Key insight**: With step-based polecat sessions (`gt mol step done` restarts session each step), polecats are either working a step or starting a step. "Nudge counts across sessions" becomes less meaningful.

## New Design: Linear Patrol + Task Tool Parallelism + Cleanup Wisps

### Patrol Shape (Deacon-style)

```
inbox-check -> process-cleanups -> check-refinery -> survey-workers -> context-check -> loop
```

No dynamic arms. No fanout gates. Linear and simple.

### Key Changes

| Aspect | Old (Christmas Ornament) | New (Linear Patrol) |
|--------|--------------------------|---------------------|
| Per-polecat inspection | mol-polecat-arm bonded dynamically | Task tool subagents within survey-workers |
| State tracking | Persistent nudge counts in handoff bead | Fresh observation each cycle (discover from beads timestamps) |
| Cleanup queue | Explicit list in patrol state | Cleanup wisps (finalizer pattern) |
| Parallelism | Molecule arms (fanout gate) | Task tool subagents |
| Aggregation | waits_for: all-children | Task tool returns |

### The Finalizer Pattern (Cleanup Wisps)

When POLECAT_DONE arrives, Witness creates a cleanup wisp:
```bash
bd create --wisp --title "cleanup:ace" --labels cleanup,polecat:ace
```

The wisp's existence IS the pending cleanup. Witness processes these in `process-cleanups` step:
- Verify git clean, issue closed, commits exist
- Kill session, remove worktree
- Burn the wisp

Failed cleanups? Leave wisp, retry next cycle. GC-style finalization.

### Task Tool Parallelism

Instead of molecule arms, use Claude's Task tool for parallel polecat inspection:

```markdown
## survey-workers step

For each polecat, launch a Task tool subagent:
- Capture tmux state
- Assess working/idle/error/done
- Check beads for step progress
- Decide and execute action (nudge/escalate/none)

Task tool handles parallelism. No molecule machinery needed.
```

## Implementation

- [x] Draft mol-witness-patrol-v2.formula.toml (linear patrol)
- [ ] Test new patrol formula
- [ ] Deprecate mol-polecat-arm
- [ ] Remove fanout gate dependency

## Files

- `.beads/formulas/mol-witness-patrol-v2.formula.toml` - New linear patrol
- `.beads/formulas/mol-witness-patrol.formula.toml` - Old Christmas Ornament (to deprecate)

## Success Criteria

- Witness patrols work with 3+ polecats using Task tool parallelism
- Cleanup wisps correctly track pending cleanups
- No persistent nudge state - fresh observation each cycle
- Simpler, more Gas Town-y design


Digest: mol-deacon-patrol

Patrol 16: All healthy


session-gc

Clean dead sessions. Run gt gc --sessions.


Create rig settings/ directory for rig configuration

Replace .gastown/ with visible settings/ at rig level:
- Create <rig>/settings/ directory
- Move .gastown/config.json → settings/config.json (theme, merge_queue, max_workers)
- Create settings/namepool.json for pool settings (style, max - not state)
- Create settings/roles/ for per-role overrides (optional)
- Update RigConfig type to reference settings/
- Update loader to read from settings/


mol-deacon-patrol


Merge: nux-1767083432904

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


Digest: mol-deacon-patrol

Patrol complete: inbox clear, agents healthy, killed 3 orphan processes, noted 1 orphaned in_progress issue


Architecture: beads config and direct landing docs

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


Handle callbacks from agents

Handle callbacks from agents.

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

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

**WITNESS_PING**:
Witnesses periodically ping to verify Deacon is alive. Simply acknowledge
and archive - the fact that you're processing mail proves you're running.
Your agent bead last_activity is updated automatically during patrol.
```bash
gt mail archive <message-id>
```

**HELP / Escalation**:
Assess and handle or forward to Mayor.
Archive after handling:
```bash
gt mail archive <message-id>
```

**LIFECYCLE messages**:
Polecats reporting completion, refineries reporting merge results.
Archive after processing:
```bash
gt mail archive <message-id>
```

**DOG_DONE messages**:
Dogs report completion after infrastructure tasks (orphan-scan, session-gc, etc.).
Subject format: `DOG_DONE <hostname>`
Body contains: task name, counts, status.
```bash
# Parse the report, log metrics if needed
gt mail read <id>
# Archive after noting completion
gt mail archive <message-id>
```
Dogs return to idle automatically. The report is informational - no action needed
unless the dog reports errors that require escalation.

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

**Hygiene principle**: Archive messages after they're fully processed.
Keep inbox near-empty - only unprocessed items should remain.


Batch wisp squashing in Deacon maintenance

Add wisp squashing to Deacon's maintenance duties:
- Patrol plugin to find orphaned/completed wisps across all rigs
- Squash completed patrol wisps to digests
- Burn abandoned wisps that have no audit value
- Part of the hygiene/cleanup system

Also: Witness polecat shutdown should spawn its own short wisp for the cleanup protocol.


Document hookable mail in all role templates and priming

Update documentation for hookable mail beads:

## Role Templates (internal/templates/roles/)
- boot.md.tmpl
- crew.md.tmpl
- deacon.md.tmpl
- mayor.md.tmpl
- polecat.md.tmpl
- refinery.md.tmpl
- witness.md.tmpl

## Priming
- internal/cmd/prime.go output

## Key Documentation Points
1. GUPP applies to mail: 'If hooked, execute'
2. Two use cases: hook existing mail, hook new instructions via gt handoff
3. Execution model: read mail, interpret, execute prose instructions
4. Successor startup: `gt hook` shows mail details, read and act

## Section to Add (adapt per role)
```markdown
## Hookable Mail

Mail beads can be hooked for ad-hoc instruction handoff:
- `gt hook attach <mail-id>` - hook existing mail
- `gt handoff -m "..."` - create and hook new instructions

If you find mail on your hook, GUPP applies: read it, execute the instructions.
```


Digest: mol-deacon-patrol

Patrol 6: quick pass


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 5: 11 sessions, all healthy


Add stale-attachments doctor check

Add gt doctor check for work stale on hook without progress.

Check: stale-attachments
Warning if: Attached molecule has no activity for >24h
Suggestion: Check agent status, consider nudge or reassignment


Move disk 1: A → B

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


Merge: furiosa-1767079892643

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


Patrol hygiene: Witness/Refinery/Deacon inbox cleanup

## Summary
Patrol roles should clean up their inboxes as part of normal operation, not let messages accumulate.

## Witness Patrol Cleanup
- POLECAT_STARTED: archive after acknowledging
- POLECAT_DONE: archive after cleanup complete
- LIFECYCLE requests: archive after processing
- Keep only: active work, unprocessed requests

## Refinery Patrol Cleanup
- MR Ready: archive after merge/reject decision
- Swarm notices: archive after dispatch
- Keep only: pending MRs in queue

## Deacon Patrol Cleanup
- Rotate daemon.log when >10MB
- Prune state.json of dead sessions
- Archive old daemon logs (gzip, date-suffix)

## Implementation
Each patrol molecule should have a 'cleanup' phase at end of cycle.

## Related
- mol-town-shutdown (nuclear cleanup)
- mol-witness-patrol, mol-refinery-patrol, mol-deacon-patrol


mol-sync-workspace: Move cleanup-worktrees earlier in step order


Move disk 7: C → A

Move disk 7 from peg C to peg A. (Move 320/1023)


Move disk 1: C → A

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


gt spawn: beads sync warnings on fresh worktree

When spawning fresh polecats, seeing 'Warning: beads sync: exit status 1' and 'Warning: beads push: exit status 1'. Worktrees are created but beads state may not be properly synced.


Move disk 3: B → C

Move disk 3 from peg B to peg C. (Move 852/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.

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


mol-deacon-patrol


Fix golangci-lint errcheck warnings (~160 issues)

Running golangci-lint shows ~160 errcheck warnings for unchecked error returns.

Common patterns:
- t.SetEnvironment() return values
- os.WriteFile(), os.RemoveAll()
- MarkFlagRequired() on cobra commands
- Various manager methods

Run: golangci-lint run ./...

Could batch fix with:
1. Add explicit _ = for intentionally ignored errors
2. Handle errors properly where they matter
3. Consider adding //nolint:errcheck for cobra flag setup


gt nudge doesn't work with crew addresses

## Bug

`gt nudge beads/crew/dave "message"` fails because it uses the polecat session manager which produces wrong session names.

## Expected
Session name: `gt-beads-crew-dave` (hyphen)

## Actual
Session name: `gt-beads-crew/dave` (slash, from polecat manager)

## Root Cause

In nudge.go line 46-57, parseAddress returns polecatName=`crew/dave`, then SessionName keeps the slash.

## Fix

Detect `crew/` prefix and use crewSessionName() instead.


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 5: All green


Move disk 1: C → A

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


Implement

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

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


Move disk 2: B → A

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


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.


Merge: keeper-mjtn0wgm

branch: polecat/keeper-mjtn0wgm
target: main
source_issue: keeper-mjtn0wgm
rig: gastown


gt status should show runtime state, not just structure

## Problem
`gt status` shows structural info (which crews exist) but not runtime reality (which sessions are running).

## Current Output
- Shows 'Crews: [dave emma zoey]' but doesn't indicate dave is crashed
- Missing Deacon from output entirely
- Hooks shown but unclear if agents are alive

## Expected
- Show which tmux sessions are actually running
- Indicate crashed/missing sessions with warning
- Include all roles (Mayor, Deacon, Witnesses, Refineries, Crews)
- Distinguish between:
  - Structure: what COULD run
  - Runtime: what IS running

## Example Better Output
```
Agents
   mayor          ✓ running (gt-mayor)
   deacon         ✓ running (gt-deacon)

Rigs
   beads
      witness     ✓ running
      refinery    ✓ running
      crew/dave   ✗ CRASHED (session missing)
      crew/emma   ✓ running
   gastown
      witness     ✓ running
      refinery    ✓ running
      crew/max    ✗ CRASHED (session missing)
```


Digest: mol-deacon-patrol

Patrol 9: All healthy


Move disk 2: B → A

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


Swarm remaining gt-8tmz P3/P4 issues

## Swarm Plan for Molecule Algebra Completion

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

### Swarmable Issues (6 total)

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol cycle 10: all healthy


Merge: gt-xqh3y

branch: polecat/eli-mjufuh2g
target: main
source_issue: gt-xqh3y
rig: gastown


Move disk 5: A → B

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


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


load-context

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

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


Merge: dementus-mjxc9ivl

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


Digest: mol-deacon-patrol

Patrol cycle 4: All agents healthy


Update Mayor startup protocol for bootstrap

Teach Mayor to respond to "boot up gas town" by slinging mol-gastown-boot.

## Current Protocol

1. Announce: "Mayor, checking in."
2. Check mail
3. If handoff, continue
4. Await user instruction

## Enhanced Protocol

1. Announce: "Mayor, checking in."
2. Check mail
3. If handoff, continue
4. **If user says "boot"/"startup"/"bootstrap":**
   - Sling mol-gastown-boot as wisp
   - Execute verification-gated steps
   - Report town status when complete
5. Otherwise await instruction

## Trigger Phrases

- "boot up gas town"
- "bootstrap the town"
- "start gas town"
- "bring up the town"

## Execution

Mayor runs the molecule manually (not via subagent):

```
1. Bond the proto: bd mol bond mol-gastown-boot --wisp
2. For each step:
   a. Run action command
   b. Loop verification with backoff
   c. On stall, run recovery
   d. Close step when verified
3. Squash wisp with summary
4. Report: "Gas Town is up. All agents healthy."
```

## CLAUDE.md Update

Add to Mayor CLAUDE.md:

```markdown
## Bootstrap Command

When user requests town bootstrap:
1. gt sling gastown-boot mayor/ --wisp
2. Execute molecule steps with verification
3. Keep trying until all agents healthy
4. No timeouts - you are the town engineer
```


witness Handoff


Digest: mol-deacon-patrol

Patrol cycle 1: All healthy - 19 polecats, witness/refinery running, 3 MQ items, no zombies


Move disk 1: B → C

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


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

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

## Usage

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

## Behavior

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

## Output

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

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

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

## If no next step

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

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

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

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


Move disk 1: A → B

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


Merge: slit-1767073379145

attached_args: Code review

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


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

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

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


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-test - The source issue ID being worked on


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol cycle 5: All healthy


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


Config directory and schema for messaging

Create ~/gt/config/ directory structure for messaging configuration.

## Deliverables

1. Create ~/gt/config/ directory
2. Define JSON schema for lists.json:
   ```json
   {
     "oncall": ["mayor/", "gastown/witness"],
     "cleanup/gastown": ["gastown/witness", "deacon/"]
   }
   ```
3. Define JSON schema for queues.json (if separate from lists)
4. Add config loading utility in internal/config/

## Acceptance
- Config directory exists
- Schema documented
- Load/parse functions work


Digest: mol-deacon-patrol

Patrol cycle 8: All healthy


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 8: all clear, handing off for fresh context


Digest: mol-deacon-patrol

Patrol 18: nominal


Hook system for event extensibility

GGT needs hook system for extensibility like PGT.

## Event Types
```go
type Event string
const (
    EventPreSessionStart  Event = "pre-session-start"
    EventPostSessionStart Event = "post-session-start"
    EventPreShutdown      Event = "pre-shutdown"
    EventPostShutdown     Event = "post-shutdown"
    EventOnPaneOutput     Event = "on-pane-output"
    EventSessionIdle      Event = "session-idle"
    EventMailReceived     Event = "mail-received"
    EventWorkAssigned     Event = "work-assigned"
)
```

## Hook Configuration
File: .claude/hooks.json or .gastown/hooks.json
```json
{
  "hooks": {
    "pre-shutdown": [
      {"type": "command", "cmd": "./scripts/pre-shutdown.sh"}
    ],
    "on-pane-output": [
      {"type": "command", "cmd": "./scripts/activity-monitor.sh"}
    ]
  }
}
```

## Hook Types
1. **Command**: Execute external script
2. **Built-in**: Internal Go functions (pre-shutdown checks)

## Hook Interface
```go
type HookRunner struct {
    config *HookConfig
}

type HookResult struct {
    Success bool
    Message string
    Block   bool  // For pre-* hooks: should operation be blocked?
}

func (r *HookRunner) Fire(event Event, ctx *HookContext) []HookResult
```

## CLI Commands
```
gt hooks list [<event>]    # List registered hooks
gt hooks fire <event>      # Manually fire for testing
gt hooks test [--all]      # Validate hook config
```

## Integration Points
- internal/session/manager.go: Fire pre/post session hooks
- internal/mail/router.go: Fire mail-received hook

## New Package
internal/hooks/
├── types.go    # Event, HookConfig, HookResult
├── runner.go   # HookRunner, Fire()
└── builtin.go  # Built-in hooks (pre-shutdown checks)

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

## Acceptance Criteria
- [ ] Hook config loading from JSON
- [ ] Command hooks execute subprocess
- [ ] Pre-shutdown hook integration with session stop
- [ ] CLI for listing and testing hooks


Digest: mol-deacon-patrol

Patrol 89: All healthy


Move disk 5: B → C

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


Digest: 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.

## 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 mail mark/delete: Basic message operations

Add `gt mail mark` and `gt mail delete` commands.

### gt mail mark
```
gt mail mark <id> --read
gt mail mark <id> --unread
```
- Update message read status in inbox.jsonl

### gt mail delete
```
gt mail delete <id> [--force]
```
- Remove message from inbox
- Confirm unless --force

**Implementation:**
- Add to internal/cmd/mail.go
- Add MarkRead(), Delete() to internal/mail/mailbox.go
- Rewrite inbox.jsonl without deleted message


Burn and respawn or loop

Burn and let daemon respawn, or exit if context high.

Decision point at end of patrol cycle:

If context is LOW:
- **Sleep 60 seconds minimum** before next patrol cycle
- If town is idle (no in_progress work), sleep longer (2-5 minutes)
- Return to inbox-check step

**Why longer sleep?**
- Idle agents should not be disturbed
- Health checks every few seconds flood inboxes and waste context
- The daemon (10-minute heartbeat) is the safety net for dead sessions
- Active work triggers feed events, which wake agents naturally

If context is HIGH:
- Write state to persistent storage
- Exit cleanly
- Let the daemon orchestrator respawn a fresh Deacon

The daemon ensures Deacon is always running:
```bash
# Daemon respawns on exit
gt daemon status
```

This enables infinite patrol duration via context-aware respawning.


Move disk 1: A → B

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


Cross-rig agent identity detection

## Problem

Several gt commands fail to correctly detect agent identity when operating
across rigs. Running commands from beads/crew/dave shows gastown/crew/joe
identity, or fails to resolve paths.

## Root Cause

Agent identity detection in gt commands assumes single-rig context. Cross-rig
crew paths like `beads/crew/dave` are not handled correctly.

## Scope

- gt hook - shows wrong identity from other rig crew dir
- gt peek - fails to resolve cross-rig crew paths
- gt sling - "." target not resolved to current agent

## Fix Strategy

Centralize agent identity detection to handle:
1. Current rig detection from cwd
2. Cross-rig path parsing (rig/crew/name vs rig/polecats/name)
3. "." resolution to current agent identity


Crew CLAUDE.md overwritten by polecat template

The crew worker CLAUDE.md files (crew/max, crew/joe, crew/jack) have been overwritten with the polecat-CLAUDE.md template content.

**Expected**: Crew workers should have mayor-like context (they share the rig repo, work on main branch, plan work)

**Actual**: Crew CLAUDE.md says 'Polecat ace' and includes polecat-specific instructions (don't push to main, wait for Witness to kill session, etc.)

**Impact**:
- Crew workers getting wrong identity context
- Ready Front planning guidance in gotchas section was lost
- Crew workers told not to push to main (but they should)

**Root cause**: Likely gt polecat template deployment hit crew directories

**Fix needed**:
- Restore crew CLAUDE.md template (or create one if missing)
- Ensure template deployment only targets polecats/ directories
- Add Ready Front planning section to crew template


Digest: mol-deacon-patrol

Patrol 7: all quiet


Move disk 1: A → B

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


EXTERNAL: Beads Messaging & Knowledge Graph (bd-kwro)

Tracking issue for external dependency on Beads v0.30.2 messaging features.

Beads epic: bd-kwro in ~/src/beads (steveyegge/beads repo)

This blocks GGT work that depends on:
- bd mail send/inbox/read/ack commands
- message issue type
- replies_to threading
- Hooks system for notifications
- Identity configuration

GGT mail commands will be thin wrappers around bd mail once available.

When bd-kwro ships in Beads v0.30.2, close this and unblock dependent work.


Digest: mol-deacon-patrol

Patrol 122: All agents healthy, no incidents


Digest: mol-deacon-patrol

Patrol 70: Routine


Digest: mol-deacon-patrol

Patrol cycle 6: All healthy


Digest: mol-deacon-patrol

Patrol 7: Quiet


ensure-beads-witness

Start the beads rig Witness.

## Action
```bash
gt witness start beads
```

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

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

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


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.


gt crew at/attach: Start session in crew workspace

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


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 8: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol 10: All clear


Digest: mol-deacon-patrol

Patrol 7: routine, all healthy


Polecat template cleanup

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


boot

Spawned. Verify the polecat starts working.

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

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

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


Move disk 1: B → C

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


Fix failing beads tests: TestIntegration and TestPolecatWorkMolecule


Move disk 2: A → C

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


Move disk 2: C → B

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


Session ended: gt-mayor


Outpost CLI commands: gt outpost list/status/add

## Overview

CLI commands for managing outposts.

## Commands

```bash
# List configured outposts
gt outpost list
NAME            TYPE       WORKERS   STATUS
local           local      2/4       healthy
gce-burst       ssh        0/8       healthy
cloudrun-burst  cloudrun   0/20      healthy

# Detailed status
gt outpost status [name]
Outpost: cloudrun-burst
Type: cloudrun
Project: my-gcp-project
Region: us-central1
Service: gastown-worker
Active Workers: 3/20
Cost (today): $0.42
Status: healthy

# Add new outpost interactively
gt outpost add
? Outpost type: [local/ssh/cloudrun]
> cloudrun
? Name: cloudrun-burst
? GCP Project: my-gcp-project
...

# Add via flags
gt outpost add cloudrun --name burst --project my-proj --region us-central1

# Remove outpost
gt outpost remove <name>

# Test connectivity
gt outpost ping <name>
```

## Files

- `cmd/gt/outpost.go` - Cobra command group
- `cmd/gt/outpost_list.go`
- `cmd/gt/outpost_status.go`
- `cmd/gt/outpost_add.go`

Depends on: gt-9a2.3 (config/manager)


Digest: mol-deacon-patrol

deacon patrol: 21 cycles complete


Digest: mol-deacon-patrol

Patrol cycle 22 complete. All 3 rigs healthy. No orphans, gates, convoys, or plugins. Quick cycle.


convoy --notify flag doesn't actually notify

The gt convoy create --notify flag is captured but only stored in description. No code sends notification on convoy completion.


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

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


plugin-run

Execute plugins from ~/gt/plugins/. Check gates, run eligible plugins.


Digest: mol-deacon-patrol

Patrol 107: All healthy


Digest: mol-deacon-patrol

Patrol 9: healthy


Merge: nux-1767087680976

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


Remove bd sync instruction from polecat startup workflow

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

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

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

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

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

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 3: all clear


Digest: mol-deacon-patrol

Patrol 12: Quiet


Digest: mol-deacon-patrol

Patrol 14


Digest: mol-deacon-patrol

Patrol 12: Routine


max Handoff


Move disk 7: C → A

Move disk 7 from peg C to peg A. (Move 704/1023)


Move disk 2: B → A

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


Convert MR queue to wisp storage

MR queue should use wisp storage (.beads-wisp/) instead of durable beads.

## Design (Simplified)

With refinery as worktree, polecats and refinery share the same machine. No cross-machine MR coordination needed. Wisps are the natural fit.

### Storage
- Location: `.beads-wisp/mq/<mr-id>.json`
- Format: Same MRFields structure (branch, target, source_issue, worker, rig)
- Lifecycle: Create on submit, delete after merge

### Code Changes

1. **MR Creation** (done.go, mq_submit.go)
   - Write to `.beads-wisp/mq/` instead of `bd create --type=merge-request`
   - Generate ID: `mr-<timestamp>-<random>` or similar

2. **Refinery Query** (refinery/manager.go, engineer.go)
   - Read from `.beads-wisp/mq/` directory
   - List files, parse JSON, process in order

3. **Cleanup**
   - Delete MR file after successful merge
   - On failure, leave file (refinery retries)

### What Stays in Beads
- Source issues (the work being merged) - still tracked in beads
- Merge commits reference source issue ID
- `bd close <issue>` still happens on merge

### Benefits
- No sync overhead for transient MR state
- Simpler model (file per MR, delete when done)
- Consistent with wisp philosophy (ephemeral operational state)

### Not Needed
- Digest squashing (MRs are deleted, not accumulated)
- Cross-machine visibility (single-machine architecture)


Move disk 1: B → C

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


go install may fail for new users - private repo

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

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

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

This will be the first command new users try.


Digest: mol-deacon-patrol

Patrol 1: All agents healthy, inbox empty, 1 dog idle


Digest: mol-deacon-patrol

Patrol 13: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol 8: Nominal


Move disk 1: B → C

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


gt-gastown-polecat-bravo

gt-gastown-polecat-bravo

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


Move disk 1: A → B

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


Remove doctor staleness detection

**File:** doctor/stale_check.go (lines 11-48)

**Current behavior:**
- DefaultStaleThreshold = 1 hour hardcoded
- Scans molecules for in_progress status older than threshold
- Reports "stale" molecules automatically

**Fix:**
- Remove automatic staleness detection from doctor
- Doctor becomes pure diagnostic tool (reports facts, not judgments)
- Deacon molecule step does "orphan-check" instead:
  "Find issues in_progress with no active polecat"

**Lines to remove:**
- stale_check.go:13 (DefaultStaleThreshold constant)
- stale_check.go:243-256 (staleness classification logic)


Move disk 1: C → A

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


Interactive prompts for destructive operations

Add interactive confirmations for destructive operations.

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

## Implementation Options

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

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

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

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

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


Merge: gt-3x1

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


Day 1.4c: Create polecat agent bead lifecycle

Define ephemeral polecat agent bead lifecycle.

Polecats need agent beads for ZFC compliance (self-report state).

Lifecycle:
1. On spawn: Create agent bead
   ```yaml
   id: gt-polecat-<rig>-<name>
   type: agent
   role_type: polecat
   rig: <rig>
   state: spawning
   hook_bead: <assigned-issue>
   ```

2. On Claude ready: Update state=working

3. On completion: Update state=done

4. On nuke: Delete agent bead

Commands needed:
- gt polecat spawn creates agent bead
- gt polecat nuke deletes agent bead
- Polecat updates own state via bd agent state

Note: This ensures Witness can read polecat state from beads instead of tmux scraping.

Implemented polecat agent bead lifecycle: spawn creates bead with state=spawning, nuke deletes bead. State updates (spawning→working→done) require bd agent state command (beads CLI enhancement).


Digest: mol-deacon-patrol

Patrol #17


Handoff mail not delivered to mayor inbox

Town log shows predecessor handed off at 12:59:33 with message about gt-7psb8, but gt mail inbox shows 0 messages. The handoff context was lost.

Reproduction:
1. Mayor runs gt handoff with -s 'context'
2. New mayor session starts
3. gt mail inbox shows empty

Expected: Handoff mail in inbox

(Moved from hq-zs2t8)


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 1: C → A

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


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol #11


ZFC #9: Explicit MR registration instead of branch parsing

**ZFC Violation:** internal/refinery/manager.go:346-370

Go infers work metadata from branch naming conventions:
```go
pattern := regexp.MustCompile(`^polecat/([^/]+)(?:/(.+))?$`)
worker := matches[1]
issueID = matches[2]
```

**ZFC-compliant solution:**
Polecats register MRs with explicit structured data:
- `gt mq submit --worker=nux --issue=gt-xyz --branch=polecat/nux/gt-xyz`
- Creates MR bead with explicit fields
- No regex parsing of branch names

**Benefits:**
- Work metadata is explicit, not inferred
- Branch naming can evolve without breaking refinery
- Audit trail in beads

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


Merge: gt-svdsy

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


Add keyboard navigation and filtering

Keyboard navigation: j/k or arrows to move, enter to expand/collapse, q to quit. Filtering: by rig name, worker name, event type. Search within activity stream.


Account management for multi-account Claude Code usage

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


Pinned beads architecture implementation

Implement the pinned beads architecture from docs/pinned-beads-design.md

Phases:
1. Doctor checks for hook validation
2. Dashboard visibility (gt hooks, gt dashboard)
3. Protocol enforcement (self-pin, audit trail)
4. Documentation updates


Digest: mol-deacon-patrol

Patrol 11: Nominal


Witness MVP: Automated Polecat Lifecycle

Implement the Witness agent - per-rig 'pit boss' that manages polecat lifecycles.

The Witness enables hands-free swarming by automating:
- Spawning polecats for ready work
- Monitoring worker health
- Processing shutdown requests
- Cleaning up worktrees when done
- Escalating stuck workers to Mayor

Without Witness, humans must manually spawn, monitor, and kill each polecat.

## Core Loop

```
while True:
  # Handle pending shutdowns
  for polecat in polecats where state == pending_shutdown:
    verify git clean
    kill session
    remove worktree
    delete branch

  # Spawn for ready work
  ready = bd ready --parent=<epic> if epic else bd ready
  for issue in ready:
    if active_workers < max_workers:
      gt spawn --issue <id>

  # Check worker health
  for polecat in active polecats:
    if stuck (no progress for 30 min):
      nudge or escalate

  sleep 60
```

## Blocking Bugs to Fix
- gt-dsfi: handoff deadlock
- gt-n7z7: refinery foreground race condition
- gm-c6b: mail coordination (town vs rig beads)


Move disk 1: C → A

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


load-context

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

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


Backup check for zombie polecats

Defense-in-depth check for zombie polecats that Witness should have cleaned.

**Why this exists:**
The Witness is responsible for nuking polecats after they complete work (via POLECAT_DONE).
This step provides backup detection in case the Witness fails to clean up.

**Zombie criteria:**
- State: idle or done (no active work assigned)
- Session: not running (tmux session dead)
- No hooked work (nothing pending for this polecat)
- Last activity: older than 10 minutes

**Run the zombie scan:**
```bash
gt deacon zombie-scan --dry-run
```

**If zombies detected:**
1. Review the output to confirm they are truly abandoned
2. Run without --dry-run to nuke them:
   ```bash
   gt deacon zombie-scan
   ```
3. This will:
   - Nuke each zombie polecat
   - Notify the Mayor about Witness failure
   - Log the cleanup action

**If no zombies:**
No action needed - Witness is doing its job.

**Note:** This is a backup mechanism. If you frequently find zombies,
investigate why the Witness isn't cleaning up properly.


Protocol: Type System for Formulas

Protocols define interfaces that formulas implement - a type system for workflows.

## Concept

```toml
# reviewable.protocol
[protocol]
name = "Reviewable"

[requires]
steps = ["review"]  # Must have a step tagged "review"
outputs = ["review_decision"]  # Must produce this

[guarantees]
"review completes before any deploy step"
```

Formulas declare: `implements = ["Reviewable", "Deployable"]`

System verifies compliance statically.

## Use Cases

1. Ensure all deploy formulas have review steps
2. Define compliance requirements as protocols
3. Enable formula discovery: "Give me all Deployable formulas"
4. Validate formula composition compatibility

## Properties

- Static verification (before execution)
- Composable (protocol can extend protocol)
- Documentation value (self-describing contracts)

## Open Questions

1. Protocol syntax - embedded in formula or separate files?
2. Verification timing - cook time? load time?
3. Protocol versioning - how do protocols evolve?
4. Inheritance - can protocols extend other protocols?

## Related

- docs/formula_evolution.md - "Formula Schemas" section
- gt-8tmz - molecule algebra


Digest: mol-deacon-patrol

Patrol 101-120 complete: Cleaned 42 stale wisps, health pings sent to all witnesses/refineries, all agents healthy, no orphans, 1 idle dog


Merge: gt-znma3

branch: polecat/nux-mjtnycav
target: main
source_issue: gt-znma3
rig: gastown
agent_bead: gt-gastown-polecat-nux


Merge: capable-1767084028536

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


Digest: mol-deacon-patrol

Patrol 8: All clear


Digest: mol-deacon-patrol

Patrol 9: routine


Move disk 5: A → B

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


Digest: mol-deacon-patrol

Patrol 6: Quiet


Digest: mol-deacon-patrol

Patrol complete: inbox empty, 2 polecats working, all agents healthy


Digest: mol-refinery-patrol

Patrol: Closed 21 merge requests that were already merged to main. All tests passed. Queue now empty.


Crew Role Definition

You are a Crew Worker - a human-managed persistent workspace within a rig.

Unlike polecats which are witness-managed and transient, crew workers are:
- Persistent: Not auto-garbage-collected
- User-managed: Overseer controls lifecycle
- Long-lived identities: Keep your name across sessions
- Gas Town integrated: Mail, handoff mechanics work

session_pattern: gt-{rig}-crew-{name}
work_dir_pattern: {town}/{rig}/crew/{name}
needs_pre_sync: true
start_command: exec claude --dangerously-skip-permissions

default_molecule: null
capabilities:
  - autonomous_work
  - beads_access
  - git_operations
  - mail_communication

## Core Responsibilities

1. Execute assigned work autonomously
2. Track progress via beads (bd commands)
3. Communicate via mail when blocked or complete
4. Maintain clean git state
5. Hand off context when cycling sessions

## Propulsion Principle

If you find something on your hook, YOU RUN IT.

Hook has work then Run it. Hook empty then Check mail. Nothing then Wait for overseer.

## Session End Protocol

- git status, git add, bd sync, git commit, git push
- gt handoff - hand off to fresh session

## Key Commands

- gt mol status - Check your hook
- bd ready - Find next step
- bd close <id> - Mark work complete
- gt mail inbox - Check messages
- gt handoff - Cycle to fresh session


gt-polecat-gastown-ace

gt-polecat-gastown-ace

role_type: polecat
rig: gastown
agent_state: running
hook_bead: gt-795e8
role_bead: null


CLI: cleanup commands for stale state

Cleanup commands for recovering from stale state.

## Commands

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

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

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

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

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

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

## New File
internal/cmd/cleanup.go

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


Digest: mol-deacon-patrol

Patrol complete: 20 cycles, handing off


Refactor sling to hook plus handoff

Replace gt sling with gt hook (durability) and gt handoff bead (hook+restart)


Keepalive signal from bd/gt commands

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

## Implementation

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

## Usage by Daemon

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

## Benefits

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


Digest: mol-deacon-patrol

Cycle 14: quiet


gt sling should accept raw issues, not just molecules

Currently gt sling only works with molecules. When you try to sling a raw issue:

  gt sling gt-9uy0 gastown/crew/max
  Error: invalid thing: issue not found

Options:
1. Auto-wrap issues in a simple work molecule (mol-issue-work?)
2. Create a minimal 'envelope' molecule on the fly
3. Just pin the issue directly without a molecule wrapper

The friction of needing a molecule for every piece of work discourages using the sling mechanism for ad-hoc tasks.

Related: crew workers often want to pick up an issue without formal molecule choreography.


Test Polecat Arm

Test child for bonding pattern


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 439/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.

## 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: B → C

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


Digest: mol-deacon-patrol

Patrol 126: All healthy


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

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

## Variables

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

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

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

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

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

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

Calculate: minutes since last activity.
Needs: capture

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

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

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

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

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

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

Record decision and rationale.
Needs: load-history

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

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

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

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

**none**: No action needed.

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

## Output

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

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


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 523/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-f14c
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Digest: mol-deacon-patrol

Patrol 17


Move disk 1: B → C

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


Move disk 1: C → A

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


Move disk 1: A → B

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


Add audit trail for hook detach operations

Log detachment events for debugging and monitoring.

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


test sling pinned


Workspace detection: Find() walking up directory tree

Find workspace root by walking up directory tree looking for Gas Town markers.

## Detection Logic

Walk up from current directory, looking for:
1. `config/town.json` - Primary marker (visible config dir per gt-iib)
2. `mayor/` directory at town level - Secondary marker

Stop at filesystem root if neither found.

## Interface

```go
// Find locates the town root from the given directory
func Find(startDir string) (string, error)

// FindOrError is like Find but returns a user-friendly error
func FindOrError(startDir string) (string, error)
```

## Return Values

- Success: Absolute path to town root
- Not found: Empty string + specific error
- Error: Empty string + wrapped error

## Edge Cases

- Symlinks: Follow them (use filepath.EvalSymlinks)
- Permissions: Return error if can't read directory
- Nested towns: Return nearest ancestor (shouldn't happen in practice
EOF
)


Digest: mol-deacon-patrol

Patrol 2: All agents healthy, no issues.


gt done: Require pushed branch before MR creation

gt done currently creates MR bead without verifying the branch is pushed.

## Problem
Polecat can run `gt done` with unpushed commits. MR bead references a branch that doesn't exist on remote. Work is lost when polecat is nuked.

## Fix
In done.go runDone():
```go
// Before creating MR bead
status, err := g.CheckUncommittedWork()
if status.UnpushedCommits > 0 {
    return fmt.Errorf("branch has %d unpushed commits; run 'git push' first", status.UnpushedCommits)
}
```

## Already Have
- `computeCleanupStatus()` checks this but only reports, doesn't block
- Just need to make it a hard error


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol 10: OK


ensure-witnesses

Parallel container: Start all rig witnesses.

## Execution
Children execute in parallel. Container completes when all children complete.

## Children
- ensure-gastown-witness
- ensure-beads-witness

## Verify
All child witness steps pass verification.


Digest: mol-deacon-patrol

Patrol cycle 17: nominal


Digest: mol-deacon-patrol

Patrol 11: all quiet


Chemistry UX commands from Beads

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

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


Define PlatformAdapter interface

Define the PlatformAdapter interface in Go. The interface specification is already
documented in ~/gt/docs/hop/PLATFORM-OF-PLATFORMS.md (lines 118-152).

**Location**: Create `internal/hop/platform.go` in the beads repo

**Interface methods** (from doc):
- Registration: GetPlatformID, GetPlatformMetadata
- Identity: MapIdentity, GetSovereigntyTier, ResolveEntity
- Work Translation: TranslateWorkUnit, TranslateToNative
- Validation: SubmitCompletion, QueryValidations
- Skills: ExtractSkills, GetSkillOntology
- Governance: GetPlatformRules, ValidateWork
- Payment (optional): GetPaymentRails, RecordPayment
- Federation: GetFederationEndpoint, CanFederateWith

**Supporting types needed**:
- SovereigntyTier enum (see gt-jzmsj.2)
- PlatformMetadata struct
- HopEntity (maps to existing EntityRef)
- HopWorkUnit (maps to existing Issue/Bead)
- ValidationRecord (maps to existing Validation)
- SkillVector, SkillOntology (stub for now)
- GovernanceRules, Violation
- PaymentRail, Payment, Receipt

**Acceptance criteria**:
1. Interface compiles and is documented
2. Types compile with reasonable defaults
3. No implementation yet - interface only


ensure-gastown-refinery

Start the gastown rig Refinery.

## Action
```bash
gt refinery start gastown
```

## Verify
1. Session exists: `tmux has-session -t gastown-refinery 2>/dev/null`
2. Not stalled: `gt peek gastown/refinery` does NOT show "> Try" prompt
3. Queue processing: Refinery can receive merge requests

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

## OnFail
Log error. Completed polecat work will queue until Refinery recovers.


Move disk 1: C → A

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


Merge: toast-mjw7062w

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


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 587/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.

## 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 5: A → B

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


Gas Town as reference platform adapter

Implement Gas Town as the reference PlatformAdapter. This proves the interface works
and serves as a template for other platforms.

**Depends on**: gt-jzmsj.1 (interface must exist first)

**Location**: gastown repo, `internal/hop/gastown_adapter.go`

**Implementation mapping** (from ~/gt/docs/hop/PLATFORM-OF-PLATFORMS.md lines 381-398):
- Platform ID: "gastown"
- Sovereignty: Tier 2-3 (organizational/pseudonymous)
- Identity: Map BD_ACTOR format (rig/role/name) → HOP EntityRef
- Work Units: Beads (issues, molecules) → HopWorkUnit
- Validation: Refinery approvals → ValidationRecord
- Skills: Stub returning empty (future work)
- Governance: Return GUPP rules reference
- Payment: Return nil (future work)
- Federation: Return town URI

**Key mappings**:
- Issue → HopWorkUnit (1:1, most fields align)
- BD_ACTOR "gastown/crew/max" → EntityRef{Platform: "gastown", Org: "steveyegge", ID: "crew-max"}
- Validation struct → ValidationRecord (already aligned)

**Acceptance criteria**:
1. GasTownAdapter implements PlatformAdapter interface
2. MapIdentity correctly parses BD_ACTOR format
3. TranslateWorkUnit converts Issue to HopWorkUnit
4. Basic test coverage


Digest: mol-deacon-patrol

Patrol cycle 24: quick check, all healthy


mol-deacon-patrol


Move disk 1: C → A

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


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

Patrol 10: quiet


Digest: mol-deacon-patrol

Patrol complete


Test Epic: GGT MVP Validation


Move disk 2: A → C

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


gt doctor: detect orphaned code on beads-sync branch

After merging beads-sync to main, some code changes can be lost if the merge conflict resolution drops files.

Add a doctor check that runs:
  git diff main..beads-sync -- '*.go' '*.md'

If there are differences in code files (not just .beads/), warn about potentially orphaned work.

Today's incident: Merge 96c773f lost mailbox.go and router.go changes from 5791752, requiring re-implementation.

Acceptance:
- gt doctor warns if beads-sync has unmerged code changes
- Excludes .beads/ directory (expected to differ)
- Shows file list of orphaned changes


Merge: capable-mjtltnm5

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


Wire up --wisp flag for ephemeral molecules

The --wisp flag exists in gt sling but isn't wired through to bd mol.

Need:
1. bd mol run --wisp - spawn to .beads-wisp/ instead of .beads/
2. Automatic burn on molecule completion
3. Optional squash to digest for audit trail

Currently:
- sling.go sets thing.IsWisp but never uses it
- bd mol run has no --wisp flag
- .beads-wisp/ exists but nothing writes to it


Move disk 3: C → A

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


Move disk 1: C → A

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


Witness: Don't nuke polecats with open MRs or hooked work

Witness mass-murdered 11 polecats during cleanup:

Evidence from witness session:
```
gt polecat nuke gastown/slit gastown/capable
Worktrees nuked: 11 (cheedo, dag, dementus, furiosa×2, keeper, nux, rictus, slit, capable, toast)
```

Casualties:
- cheedo had open MR gt-t7g4b (branch not pushed, work lost)
- cheedo had hooked work gt-w0fqg (had to reassign)
- Unknown other work may have been lost

Pre-nuke checklist must verify:
1. No uncommitted/unpushed work
2. No open MRs awaiting merge
3. No work on hook (unless orphan recovery)
4. Issue is actually closed (not just 'done' signaled)

The witness is supposed to be a pit boss, not an executioner.

## Update: Instructions exist but were ignored

Witness CLAUDE.md HAS the pre-kill checklist:
```
Before killing ANY polecat session, verify:
[ ] 3. Check for unpushed commits
[ ] 4. Verify issue closed
[ ] 5. Verify PR submitted
```

Code for verification also exists on main (c28a0d5).

But witness still mass-murdered. Possible causes:
1. Context pressure (witness was at 4% - may have lost instructions)
2. Some aggressive prompt overriding safety checks
3. Agent non-compliance

Need: Enforcement mechanism, not just instructions.


Digest: mol-deacon-patrol

Patrol 140: All healthy