Document session cycling protocol in all templates

Add explicit lifecycle request protocol to all agent templates.

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

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

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

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


Digest: mol-deacon-patrol

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


Move disk 6: A → C

Move disk 6 from peg A to peg C. (Move 992/1023)


Digest: mol-deacon-patrol

Patrol cycle 8: All healthy, 4 polecats active (furiosa, nux, rictus, slit)


Witness startup: bond mol-witness-patrol on start

Wire up Witness to automatically bond its patrol molecule on startup.

## Desired behavior
On Witness session start:
1. gt prime detects RoleWitness
2. Check for existing in-progress patrol
3. If found: resume from current step
4. If not found: bd mol bond mol-witness-patrol --wisp
5. Output patrol context to agent

## Depends on
- gt-83k0 (mol-witness-patrol definition)
- gt-caih (handoff bead state persistence)


Digest: mol-deacon-patrol

Patrol cycle 2: All rigs healthy. No callbacks. Town idle.


Digest: mol-deacon-patrol

Patrol complete: 0 callbacks, no gates, all witnesses/refineries healthy, no orphans


Digest: mol-deacon-patrol

Patrol 6: Routine


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.


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

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

## Variables

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

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

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

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

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

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

Calculate: minutes since last activity.
Needs: capture

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

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

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

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

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

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

Record decision and rationale.
Needs: load-history

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

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

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

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

**none**: No action needed.

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

## Output

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

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


Move disk 1: C → A

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


Move disk 2: B → A

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


Digest: mol-deacon-patrol

P12: stable


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 6: quick pass


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

Patrol 6: All healthy


Digest: mol-deacon-patrol

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


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol cycle 9: All healthy


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

Patrol 116: All healthy


Move disk 1: C → A

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


Move disk 1: C → A

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


Move disk 3: B → C

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


Merge: rictus-mjw3nj1a

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


mol-deacon-patrol


Move disk 2: A → C

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


Merge: capable-1767084028536

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


CLI: spawn command

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

## Command

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

## What It Does

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

## Options

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

## Auto-Select Logic

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

## Initial Context

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

<description>

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

## Implementation

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


Work on ga-rd4: Add gt polecat status command. Show detai...

Work on ga-rd4: Add gt polecat status command. Show detailed polecat status including current issue, session state, last activity time. When done, submit MR (not PR) to integration branch for Refinery.


Merge: slit-mjxc8tp2

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


Merge: rictus-1767073382273

attached_args: Code review this merge request

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


Move disk 2: A → C

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


CLI: workspace commands (init, add, list)

GGT needs workspace management commands beyond install.

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

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

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

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

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

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


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


Move disk 2: B → A

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


Digest: mol-deacon-patrol

Patrol 8: routine


Digest: mol-deacon-patrol

Patrol 18: all quiet


Digest: mol-deacon-patrol

Patrol cycle 65: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Move disk 1: B → C

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


Move disk 2: B → A

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


Merge: gt-vmk7

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


Agent bead IDs should use rig prefix, not hardcoded gt-

When spawning beads polecats, agent bead creation fails:

```
Error: invalid agent ID: agent ID must start with 'gt-' (got "bd-beads-polecat-pearl")
```

The validation is hardcoded to expect 'gt-' but beads rig uses 'bd-' prefix.

Fix: Agent bead ID validation should accept the rig's configured prefix, not hardcode 'gt-'.


Digest: mol-deacon-patrol

Patrol cycle 3: All quiet. Agents healthy. No pending work.


Digest: mol-deacon-patrol

Patrol 13: Mayor OK, 11 sessions


Digest: mol-deacon-patrol

Patrol 12: nominal


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

## Current Behavior

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

## Expected Behavior

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

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

## Example

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

## Implementation

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

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


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

## Context

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

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

## Current behavior

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

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

## Desired behavior

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

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

## Related

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


gt crew list: List crew workspaces

Implement 'gt crew list [--rig <rig>]' command:
- List all crew workers in rig(s)
- Show status (session running, last activity)
- Show current branch and git status summary
- Support --json output


Move disk 2: B → C

Move disk 2 from peg B to peg C.


Move disk 1: B → C

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


Standardize wisp creation syntax across role templates

## Task

Role templates use inconsistent syntax for creating wisps.

## Current State

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

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

## Recommended Pattern

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

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

## Templates to Update

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

## Related

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


Plugin: work-oracle (pre-dispatch analysis)

Plugin for pre-dispatch task analysis and decomposition.

## Purpose

Before dispatching workers for an epic, ask work-oracle to:
- Validate task breakdown
- Identify parallelization opportunities
- Predict conflicts between tasks
- Suggest worker count

## Hook Point

Mayor consults work-oracle before spawning workers.

## Interface

Input (via mail):
- Epic ID with proposed child issues
- Rig context (current state of codebase)

Output (via mail + bead):
- Recommended task groupings
- Dependency suggestions
- Risk assessment (which files might conflict)
- Optimal worker count

## Structure

```
<rig>/plugins/work-oracle/
├── CLAUDE.md       # Analysis prompts
├── mail/inbox.jsonl
└── state.json
```

Uses existing plugin-as-agent architecture.

## Note

Was "swarm-oracle" - renamed because there are no swarm IDs. This plugin helps plan batch work, not manage swarm entities.


Digest: mol-deacon-patrol

Patrol 20: final cycle complete, handoff time


Digest: mol-deacon-patrol

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


Move disk 4: B → A

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


Design: Polecat Beads write access

Design for granting polecats direct beads write access.

## Background

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

## Benefits

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

## Complications

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

## Subtasks (implementation)

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

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


gt done --exit: Self-terminate polecat session after MR submission

## Problem

Polecats finish work, call `gt done`, and then sit idle at Claude prompt waiting for Witness to kill them. This wastes money (idle Claude sessions still cost).

## Solution

Add `--exit` flag to `gt done` that:
1. Submits MR to merge queue (existing behavior)
2. Sends POLECAT_DONE to Witness (existing behavior)
3. Exits the Claude session immediately (new)

```bash
gt done --exit  # Submit MR and exit session
```

## Implementation

In `internal/cmd/done.go`:
1. Add `--exit` flag
2. After successful MR submission and witness notification:
   - Print final status
   - Call `os.Exit(0)` OR run `/exit` command

## Notes

- Witness still receives POLECAT_DONE and handles cleanup (nuke worktree) async
- No waiting = no idle sessions = no wasted money
- Session exit is safe because all work is pushed and MR submitted before exit


Digest: mol-deacon-patrol

Patrol 14: routine


Set GIT_AUTHOR_NAME per agent session

Set GIT_AUTHOR_NAME to actor string (e.g., gastown/crew/joe) in agent session environment. GIT_AUTHOR_EMAIL stays as workspace owner. Enables git log --author queries for agent work.


Session ended: gt-mayor


Merge: rictus-mjw3nj1a

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


Digest: mol-deacon-patrol

Patrol 13: Routine


Update harness beads redirect for GGT

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


Digest: mol-deacon-patrol

Patrol complete: inbox empty, all agents healthy, cleaned 4 orphans (gt-wx0w, gt-kp3s3, gt-6n1cy, gt-i4lo)


Digest: mol-deacon-patrol

Patrol 20: all healthy, new polecats spawning


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.


Add gt crew rename command


Agent beads hook_bead field never populated

## Problem

The witness patrol formula expects polecat agent beads to have:

  hook_bead: <current-work-id>

This field is used by the witness to see what the polecat is working on.

But looking at the code, hook_bead is never set:

1. Polecat agent bead created (polecat/manager.go:167-170) - no hook_bead
2. reportAgentState called (prime.go:1067) - passes nil for hookBead
3. UpdateAgentState preserves existing hook_bead if nil (beads.go:633-635)

Since hook_bead starts empty and is never updated, the witness cannot use
agent beads to see what polecats are working on.

## Found in commit

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

## Related to

- gt-0lop3 (Agent state lifecycle incomplete for polecats)

## Suggested fix

When a polecat is assigned work (via gt sling or similar), update the agent
bead's hook_bead field:

  bd.UpdateAgentState(agentID, 'running', &hookBeadID)


Digest: mol-deacon-patrol

Patrol 90: All healthy


Polecat spawn: Environment vars not exported to shell

Polecat sessions set tmux environment but don't export to shell before Claude

In session/manager.go Start():
  _ = m.tmux.SetEnvironment(sessionID, "GT_RIG", m.rig.Name)
  _ = m.tmux.SetEnvironment(sessionID, "GT_POLECAT", polecat)
  ...
  command = "claude --dangerously-skip-permissions"

Compare to crew_lifecycle.go which exports inline:
  claudeCmd := fmt.Sprintf("export GT_ROLE=crew GT_RIG=%s GT_CREW=%s && claude ...")

Result: Claude can't detect polecat identity, falls back to 'mayor', shows wrong hook.

Fix: Export GT_ROLE=polecat GT_RIG=X GT_POLECAT=Y inline before running Claude.


Digest: mol-deacon-patrol

Patrol complete: 17 Claude procs, 3 witnesses, 2 refineries healthy. 2 convoys open. No orphans, no cleanup needed. Inbox empty.


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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 7: All clear


Add live polling and updates

Implement live polling (500ms default) for activity updates. Merge new events into view without flickering. Show connection status indicator. Handle daemon disconnects gracefully.


Digest: mol-deacon-patrol

Patrol cycle 7: All quiet.


Move disk 1: C → A

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


Digest: mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 3: Quick scan, stable


Move disk 1: C → A

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


Day 5.0: gt status shows pinned role beads and slots

Enhance gt status to display:
- All pinned role beads (mayor, witness, refinery, polecats)
- Their current hook slot contents (what molecule/bead is attached)
- Agent state if available

This gives a single-command view of who's working on what across the town.

Example output:
```
gt status

Town: gastown
Daemon: running (pid 1234)

Agents:
  mayor/           gt-liftoff (pinned)     idle
  witness/gastown  gt-wisp-abc (patrol)    running
  refinery/gastown (empty)                 idle
  polecat/nux      gt-xyz (in_progress)    working
  polecat/rictus   (empty)                 idle
```


Merge: capable-mq

branch: polecat/capable-mq-events
target: main
source_issue: capable-mq
rig: gastown


Liftoff implementation plan in Beads

## Context

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

## Work Required

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

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

Three pillars to decompose:
1. **Agent beads** - schema, slot commands, migration
2. **Patrol ignition** - witness/refinery formula wiring
3. **Polecat lifecycle** - recycle/nuke commands, session-per-step

Key dependency trap to avoid:
- "Phase 1 blocks Phase 2" is WRONG (temporal thinking)
- "Phase 2 depends on Phase 1" is RIGHT (requirement thinking)
- Use `bd dep add <child> <parent>` where child NEEDS parent

### Phase 3: Review
Human reviews the plan in a separate session.

## Deliverable

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

## References

- gt-552hb: Swarm orchestration epic (existing, may subsume)
- gt-t6muy: Polecat lifecycle design (existing, captures session-per-step)


Digest: mol-deacon-patrol

Patrol 20: routine, all healthy


Digest: mol-deacon-patrol

Cycle 191: Nominal


Digest: mol-deacon-patrol

Patrol 7: All healthy


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


implement

Implement the solution for gt-1wmw. Follow codebase conventions.
File discovered work as new issues with bd create.

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

Depends: load-context


Merge: gt-qsvq

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


Digest: mol-deacon-patrol

Patrol 15: all quiet


Polecat identity confusion leads to direct main commits

When polecats spawn without proper identity (due to gt-si6am and gt-y41ep):
1. They think they're mayor
2. They may commit from wrong directory (mayor/rig instead of polecats/<name>)
3. Work goes directly to main, bypassing merge queue

Observed: slit pushed 'gt polecat recycle' directly to main instead of its branch

Root cause:
- gt-si6am: Wrong CLAUDE.md template (says 'Mayor Rig Context')
- gt-y41ep: Env vars not exported (falls back to mayor detection)

Impact: CRITICAL - merge queue entirely bypassed, no refinery review


Move disk 2: C → B

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


Deacon Kernel: event processing molecule architecture

Extend the Deacon from "health orchestrator" to "event processing kernel" that runs a
molecule (rounds) each wake cycle, like an OS kernel scheduler.

## Core Insight

The Deacon already has:
- Wake cycle (daemon poke, timer, lifecycle request)
- Mail as event queue
- Health scanning
- Lifecycle processing

But it is REACTIVE. This epic makes it PROACTIVE with a structured molecule:

```
Deacon Wake
├── Step 0: Session Check (should I cycle myself?)
├── Step 1: Health Scan (Mayor, Witnesses, Crew, Refineries)
├── Step 2: Lifecycle Processing (cycle/restart/shutdown requests)
├── Step 3: Plugin Execution (scheduled, event-triggered, human-requested)
├── Step 4: Event Callbacks (timers, subscriptions)
└── Step 5: Heartbeat + Wait
```

## Key Design Decisions

1. **Session cycling first** - Token costs are quadratic with session length.
   Deacon should aggressively cycle to fresh sessions. First step of every
   wake is "do I need a new session?" based on context budget.

2. **Pinned bead with marching orders** - A pinned bead (like gt prime for
   agents) defines the Deacon's rounds molecule. This is the Deacon's
   "kernel" - its operating loop.

3. **Keepalive file for daemon quieting** - Instead of daemon tmux-poking
   the Deacon (which interrupts work), Deacon writes a keepalive file.
   Daemon reads it and backs off. Worst case: Deacon forgets, gets one
   extra heartbeat it squelches.

4. **Molecule-based rounds** - The wake cycle becomes a molecule with steps.
   Each step can have plugins (inline attention). Steps can be added/modified
   by updating the pinned bead.

## Architecture

```
Go Daemon (minimal, dumb)
├── Reads {townRoot}/deacon/keepalive.json
├── If fresh: do nothing
├── If stale: poke Deacon (fallback)
└── Process lifecycle requests (still daemon's job)

Deacon (Claude agent, smart)
├── Wakes: poke, timer, mail event
├── Writes keepalive (quiets daemon for duration of rounds)
├── Runs rounds molecule:
│   ├── session-check: cycle if context budget low
│   ├── health-scan: check agents, remediate
│   ├── lifecycle: process requests
│   ├── plugins: run scheduled/triggered plugins
│   ├── events: process timer/event callbacks
│   └── complete: update heartbeat, wait
└── Reads marching orders from pinned bead
```

## Relation to Existing Work

- Extends gt-5af (Deacon infrastructure) - CLOSED
- Relates to gt-axz (Plugin architecture) - P3
- Fits into phase3-deacon of gt-ngpz (Christmas Plan)
- Enables gt-976 (Crew lifecycle) as part of health-scan step


Digest: mol-deacon-patrol

Patrol complete: 2 mayor handoffs (not for deacon), all agents healthy, no orphans


Move disk 4: B → A

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


Digest: mol-deacon-patrol

Patrol 52: All healthy


Digest: mol-deacon-patrol

Patrol 73: Routine


Schematic: Domain-Level Formula Composition

A Schematic is a coordinated set of formulas defining an entire workflow domain.

## Concept

Like an orchestra score to instrument parts - says how formulas fit together.

```toml
# shiny-engineering.schematic
[schematic]
name = "The Shiny Way"
description = "Full engineering workflow from issue to production"

[formulas]
planning = "@gastown/shiny"
development = "@gastown/polecat-work"
review = "@gastown/review"
release = "@gastown/release"

[flow]
default = "planning >> development >> review >> release"

[constraints]
all_code_reviewed = true
tests_before_deploy = true
```

## Relationship to Other Concepts

- **Schematic** (workflow dimension) = composition of Formulas
- **Campaign** (work dimension) = composition of Epics
- Schematic compiles to Campaign, like Formula compiles to Molecule

## Use Cases

1. Define "The Shiny Way" for a team/org
2. Encode compliance requirements
3. Standardize workflows across projects
4. Enable workflow reuse and sharing

## Open Questions

1. File format - TOML? YAML? Extend formula syntax?
2. Validation - how to verify schematic consistency?
3. Overrides - can project override org schematic?

## Related

- docs/formula_evolution.md
- gt-8tmz - molecule algebra


Move disk 1: C → A

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


Phase 2.1: gt spawn --molecule bonds in ephemeral

Make gt spawn molecule-aware with ephemeral bonding.

## New Flag

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

## Behavior

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

## Work Assignment Mail

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

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

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

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


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 5: clear


Extended addressing: Parse [machine:]rig/polecat

Extended addressing for cross-machine operations.

## Address Format

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

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

## Parser

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

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

## Validation

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

## Usage

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

## Backward Compatibility

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


Merge: nux-1767087680976

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


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol: 4 msgs (2 blocked on bd mol current, 2 handoffs). 11 polecats, 18 sessions. Swarm in progress.


MQ dashboard widget: queue status in TUI

Add merge queue status widget to the Bubbletea TUI dashboard.

Display:
┌─────────────────────────────────────────────────┐
│              MERGE QUEUE STATUS                  │
├─────────────────────────────────────────────────┤
│ Pending: 3   In Progress: 1   Merged (24h): 12  │
├─────────────────────────────────────────────────┤
│ QUEUE:                                          │
│   ► gt-mr-004  P0  Nux/gt-xyz     Processing... │
│     gt-mr-005  P1  Toast/gt-abc   Ready         │
│     gt-mr-006  P1  Capable/gt-def Blocked (005) │
└─────────────────────────────────────────────────┘

Interactive features:
- Navigate queue entries
- View MR details
- Retry/reject from dashboard

Depends on: gt-u1j.2 (Bubbletea TUI dashboard)

Reference: docs/merge-queue-design.md#dashboard


Messaging Channels: Unified list/queue/announce/nudge system

Implement the full messaging channel system for Gas Town.

TWO PARALLEL SYSTEMS:
1. Durable (polling): mail - list, queue, announce
2. Real-time (ephemeral): nudge - channels

ARCHITECTURE:
- Config: ~/gt/config/messaging.json (town-level)
- Messages: beads (.beads/issues.jsonl with type=message)

CHANNEL TYPES:
- list:name - Fan-out, each recipient gets copy (DONE)
- queue:name - Claim-based, exactly-once processing (gt-02431)
- announce:name - Bulletin board, read-only (gt-cqvgt)
- nudge channel:name - Real-time fan-out (gt-3txyh)

PRIORITY ORDER:
1. Queues - solves real polecat cleanup race condition
2. Nudge channels - gt broadcast mostly works but channels add precision
3. Announces - nice-to-have bulletin boards


gt feed: Activity feed command with tmux-aware modes

## Context

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

## Requirements

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

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

## Design Questions

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

## Implementation Options

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

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

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

## Related

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


Merge: furiosa-1767073359963

attached_args: Code review this merge request

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

REVIEW REJECTED by rictus: Commits claim await-signal but no such code exists. Feature removals conflict with rictus branch quality-level work. Needs clarification and reconciliation.


Molecule composition: Includes directive

Add support for molecule composition via the Includes directive.

## Format
\`\`\`markdown
## Molecule: derived-name
Includes: mol-base-molecule

## Step: additional-step
Additional instructions here.
Needs: step-from-base
\`\`\`

## Implementation
1. Add \`Includes:\` parsing to ParseMoleculeSteps()
2. Resolve included molecule by ID
3. Merge steps from included molecule
4. Allow new steps to depend on included steps
5. Support multiple includes (polymers)

## Files to modify
- internal/beads/molecule.go
- internal/beads/molecule_test.go

## Acceptance
- [ ] Parse Includes directive
- [ ] Resolve and merge included steps
- [ ] Dependencies across molecules work
- [ ] Multiple includes supported
- [ ] Tests cover composition scenarios


Add Boot shutdown to gt shutdown

gt shutdown should stop Boot if running. Currently Boot is only spawned by daemon but never explicitly stopped.


Digest: mol-deacon-patrol

Cycle 12: quiet


Digest: mol-deacon-patrol

Patrol cycle 5: all healthy


Move disk 3: C → A

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


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol cycle 5: Routine.


Day 3.7: Witness pings Deacon for second-order monitoring

Add second-order monitoring: Witnesses monitor the Deacon.

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

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

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

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

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

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


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.


Review PR #51: fix: Use hq prefix for agent beads to match town beads database

Review PR #51. Check hq prefix usage is consistent. Approve with gh pr review --approve if good.


Move disk 1: C → A

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


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 6: clear


Digest: mol-deacon-patrol

Patrol 12: All healthy


Move disk 6: A → C

Move disk 6 from peg A to peg C. (Move 32/1023)


Digest: mol-deacon-patrol

Patrol 11: All healthy, no messages


Digest: mol-deacon-patrol

Patrol 10: routine, halfway


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

Patrol 3: all healthy, no work


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.


Document bd mol bond/squash/burn CLI

Create CLI reference documentation for molecule commands:

## bd mol bond

Instantiate a proto into a runnable molecule.

```bash
bd mol bond <proto-id> [--wisp] [--assignee=<addr>]
```

- Default: creates a Mol (durable, in main beads)
- --wisp: creates a Wisp (ephemeral, in .beads-ephemeral/)
- --assignee: who will execute this molecule

## bd mol squash

Complete a molecule and generate digest.

```bash
bd mol squash <mol-id> --summary='...'
```

- For Mol: creates digest in git history
- For Wisp: evaporates (no permanent record)
- --summary: required summary of what was accomplished

## bd mol burn

Abandon a molecule without completing.

```bash
bd mol burn <mol-id> [--reason='...']
```

- Discards molecule state
- No digest created
- Use when molecule is no longer needed


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.


Witness patrol: Add banners and wisp-based execution

Bring Witness patrol up to Deacon's level of sophistication:

## Current state
- mol-witness-patrol exists (gt-qflq)
- Basic step definitions

## Needed
1. **Banners** - Print step banners like Deacon does:
   ```
   ═══════════════════════════════════════════════════════════════
     👁 POLECAT-SCAN
     Checking polecat health and nudging stale workers
   ═══════════════════════════════════════════════════════════════
   ```

2. **Wisp-based execution** - Spawn patrol as wisp, squash when complete
3. **Handoff bead attachment** - Witness needs its own handoff bead with attached_molecule
4. **Loop-or-exit step** - Context-aware cycling like Deacon
5. **Patrol summary banner** at end of each cycle

## Reference
See Deacon patrol implementation in ~/gt/deacon/CLAUDE.md


Digest: mol-deacon-patrol

Patrol 156: All healthy


Beads daemon cache stale - hook queries return wrong data

Root cause: Beads daemon has stale data. Multiple bd daemons running (4 instances). When gt hook status queries via daemon, it gets old hooked bead. When queried with --no-daemon, correct bead is shown. This is a daemon cache coherence issue, not an ID resolution bug. Workaround: Use bd --no-daemon commands or restart daemons.


Digest: mol-deacon-patrol

Patrol 98: All healthy


Move disk 1: B → C

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


Move disk 3: B → C

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


Digest: mol-deacon-patrol

Patrol 17: All clear


Merge: gt-3x1.3

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


Digest: mol-deacon-patrol

Patrol cycle 16


Digest: mol-deacon-patrol

Patrol 11: routine


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


Digest: mol-deacon-patrol

Patrol 20: all healthy


mol-deacon-patrol


gt-gastown-polecat-bix

gt-gastown-polecat-bix

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


Digest: mol-refinery-patrol

Patrol: No MRs in queue. Found 1 pending branch (gt-jq8i4) without MR bead. 8 stale branches detected (work already on main).


Merge: gt-h6eq.3

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol cycle 12: All agents healthy


Digest: mol-deacon-patrol

Patrol 1: All agents healthy, 1 message processed, no orphans


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

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

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

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

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

This should be standard Gas Town rig configuration.


Digest: mol-deacon-patrol

Patrol #20: Final cycle - all agents healthy. Beads 5 MQ pending, gastown 1 MQ pending. 1 dog idle. Clean handoff.


Missing space in error messages (handoff.go, prime.go)

Minor typo in error messages at two locations:

**handoff.go L895**:
```go
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon wisp" + protoID))
// Missing space before protoID
```

**prime.go L1061**:
Same issue.

**Fix**: Add space before protoID:
```go
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon wisp " + protoID))
```


Digest: mol-deacon-patrol

Patrol cycle 16: all healthy


Move disk 2: A → C

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


Pick next branch. Rebase on current main.

```bash
git checkout -b temp origin/<polecat-branch>
git rebase origin/main
```

If rebase conflicts and unresolvable:
- git rebase --abort
- Notify polecat to fix and resubmit
- Skip to loop-check for next branch

instantiated_from: mol-refinery-patrol
step: process-branch


Digest: mol-deacon-patrol

Patrol: slit handoff (landing protocol), polecats cleaned (0 now), 4 witness/refineries up


Digest: mol-deacon-patrol

Patrol 18: All healthy.


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 2: Quick scan, no changes


Move disk 4: B → A

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


Move disk 3: C → A

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


Digest: mol-deacon-patrol

Patrol 16: All agents healthy


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

P16: stable


gt-gastown-polecat-cheedo

gt-gastown-polecat-cheedo

role_type: polecat
rig: gastown
agent_state: running
hook_bead: null
role_bead: gt-polecat-role
cleanup_status: has_uncommitted
active_mr: gt-42whv
notification_level: null


Swarm cleanup: delete merged polecat branches and reset state

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

## Current Problem

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

## Observed After Swarm

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

## Proposed Solution

Add cleanup commands:

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

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

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

## Manual Cleanup For Now

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


Add gt role command group with env-based role detection

# gt role Command Group

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

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

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

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

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

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


Add unit tests for internal/mrqueue package

attached_args: mrqueue package tests

Add comprehensive tests for the merge request queue package.

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

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

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


Digest: mol-deacon-patrol

Patrol 20: Quiet


mol-deacon-patrol

Mayor's daemon patrol loop.

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

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


Digest: mol-deacon-patrol

Patrol 14: All agents healthy


Digest: mol-deacon-patrol

Patrol cycle 13: nominal


BUG: gt done doesn't push branch to origin - work lost when worktree deleted

## Problem

`gt done` creates a merge-request record in beads but **never pushes the branch to origin**.

When polecats are cleaned up (worktrees deleted), the branch is lost forever. The MR record exists but there's no actual branch to merge.

## Evidence

12 MQ items had `ready` status but no corresponding branches on origin. All polecat worktrees were deleted, losing all work.

## Impact

**CRITICAL**: All polecat work is silently lost unless polecats manually push (which they don't know to do).

## Fix

In `done.go`, before creating the MR:
1. `git push origin <branch>` to push the branch to remote
2. Only create MR record if push succeeds

## Location
`mayor/rig/internal/cmd/done.go:124-135`


Digest: mol-deacon-patrol

Patrol 13: clear


Retry logic: exponential backoff for transient failures

Implement retry logic for transient failures.

Retryable failures:
- Push failed (network, auth transient)
- Test flaky (config: retry_flaky_tests)
- Fetch failed (network)

Retry strategy:
- Max retries: 3 (configurable)
- Backoff: 1s, 2s, 4s (exponential)
- On final failure: treat as permanent, assign back

Non-retryable failures:
- Merge conflict
- Test consistently fails
- Build error

Track retry count in MR metadata for debugging.

Reference: docs/merge-queue-design.md#failure-recovery


Digest: mol-deacon-patrol

Patrol cycle 4: All agents healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


gt crew add: Agent bead uses hardcoded gt- prefix instead of rig prefix

When running 'gt crew add <name> --rig beads', the command tries to create an agent bead with ID 'gt-crew-beads-<name>' but beads rig uses 'bd' prefix.

Error: issue ID 'gt-crew-beads-grip' does not match configured prefix 'bd'

The agent bead ID should use the target rig's prefix, not hardcode 'gt-'.


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

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 159 complete


Work on ga-p6r: Add handoff protocol to spawn priming. En...

Work on ga-p6r: Add handoff protocol to spawn priming. Ensure polecats receive handoff context when spawned. When done, submit MR (not PR) to integration branch for Refinery.


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

## Context

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

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

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

## Background

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

## Investigation Steps

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

## Key Question

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

## Commands

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


Digest: mol-deacon-patrol

Patrol 14: All healthy, no messages


Move disk 2: A → C

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


Rewrite role templates without step lists

Update:
- prompts/roles/deacon.md
- prompts/roles/refinery.md
- prompts/roles/witness.md

Templates should describe HOW to run patrols (propulsion principle, bd mol current, bd close --continue) not WHAT the steps are. Steps come from proto beads.


Digest: mol-deacon-patrol

Patrol 9: All clear


Move disk 1: A → B

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


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


Move disk 1: C → A

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


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol cycle 2: All rigs healthy, no incidents


Digest: mol-deacon-patrol

Patrol 6: healthy


Digest: mol-deacon-patrol

Patrol 15: All healthy


Move disk 3: B → C

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


mol-deacon-patrol


Move disk 5: A → B

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


Digest: mol-deacon-patrol

Patrol 8: All clear


Digest: mol-deacon-patrol

Patrol 20: All healthy - final patrol


Digest: mol-deacon-patrol

Cycle 298: All healthy, refinery processing


Digest: mol-deacon-patrol

Patrol 3: inbox clear, all healthy


Add bd mol progress command for mega-molecule summary

New command that shows progress percentage, current step, rate, ETA without listing all steps.

Output format:
Molecule: gt-hanoi-xyz (Towers of Hanoi - 20 disks)
Progress: 347,892 / 1,048,575 (33.2%)
Current step: gt-hanoi-xyz.move-347893
Rate: ~1,200 steps/hour
ETA: ~9.7 hours remaining

Implementation in beads repo.


gt-crew-gastown-max

gt-crew-gastown-max

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


Digest: mol-deacon-patrol

Patrol cycle 2: all healthy


Merge: nux-1767141948667

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


Remove keepalive file infrastructure

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

**Current state:**
- keepalive.TouchTownActivity() writes to activity.json on every gt/bd command
- Daemon reads activity.json to calculate exponential backoff

**New model (feed-based wake):**
- Patrol agents subscribe to `bd activity --follow`
- Any beads mutation wakes agents within ~500ms
- Daemon heartbeat is recovery-focused, not wake-focused
- Read-only commands don't need to wake the town

**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):
- gt mail inbox (checking for work?)
- None identified yet

See docs/patrol-system-design.md for full feed-based wake design.


Merge: gt-5wb7

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


Merge: rictus-1767087768853

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


Digest: mol-deacon-patrol

Patrol 146: All healthy, new furiosa spawn


Digest: mol-deacon-patrol

Cycle 185: Nominal


Digest: mol-deacon-patrol

Patrol 6: all clear


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 cycle 20: final cycle before handoff


Move disk 2: C → B

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


Role prompts have mismatched startup protocols

Different role prompts describe different startup protocols:

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

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


Implement git merge logic in Engineer.ProcessMR

The Engineer module in internal/refinery/engineer.go has stub implementations for ProcessMR() and ProcessMRFromQueue() that need actual git merge logic.

## Current State
- ProcessMR() logs intent but returns failure
- ProcessMRFromQueue() same - logs and returns failure
- handleSuccess() and handleFailure() are implemented

## Required Implementation
1. **Fetch source branch**: git fetch origin <branch>
2. **Conflict check**: git merge --no-commit --no-ff to test
3. **Run tests** if configured (config.RunTests, config.TestCommand)
4. **Perform merge**: git merge with appropriate commit message
5. **Push to origin**: git push origin <target>
6. **Handle failures**: conflicts, test failures, push failures

## Context
- There are 28+ pending merge-request issues waiting for this
- Infrastructure (config, result types, success/failure handlers) is ready
- Just needs the core git operations

## Files
- internal/refinery/engineer.go - ProcessMR(), ProcessMRFromQueue()
- internal/git/git.go - may need Merge(), Fetch() methods


Add gt mail clear command for bulk inbox clearing

Currently `gt mail delete` only accepts a single message-id. Need:

1. `gt mail clear` - Clear all messages from your inbox
2. `gt mail clear <target>` - Clear another agent's inbox (e.g., `gt mail clear gastown/joe`)
3. Or: `gt mail delete --all` flag

Use case: Town quiescence - need to reset all inboxes across all workers efficiently.

Current workaround: Loop through each message ID individually, which is tedious for 50+ messages per inbox.


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 12: Routine


Digest: mol-deacon-patrol

Cycle 15


Digest: mol-deacon-patrol

Patrol 9: All agents healthy, 1 orphan process cleaned, no mail


Move disk 1: C → A

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


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 9: All healthy


Digest: mol-deacon-patrol

Patrol 65: Routine


Move disk 5: A → B

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


Mail coordination should use town-level database

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


Move disk 2: C → B

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


ZFC Cleanup: Move Go heuristics to Deacon molecule

Remove Go code that makes workflow decisions. All health checking, staleness
detection, nudging, and escalation belongs in the Deacon molecule where Claude
executes it once per minute.

## The Problem

Go code currently implements polling-based health inference:
- Daemon watches heartbeats with hardcoded thresholds
- Decides if agents are "stuck" based on timestamps
- Sends nudges, triggers restarts
- Parses mail subjects with regex to extract intent

This is a ZFC violation. Go should be message transport, not decision-maker.

## The Fix

Move all health/oversight logic to Deacon patrol molecule:
- Deacon runs once per minute
- Claude reads molecule steps, executes them
- Claude decides if agents are stuck (by checking mail, activity, etc.)
- Claude sends nudges/escalations via mail
- Go just routes messages

## Scope

1. daemon/daemon.go - heartbeat staleness logic
2. daemon/backoff.go - exponential backoff decisions
3. daemon/lifecycle.go - regex parsing of lifecycle intent
4. keepalive/keepalive.go - staleness thresholds
5. deacon/heartbeat.go - heartbeat age classification
6. doctor/stale_check.go - staleness detection
7. polecat/manager.go - state derivation from issues

## Success Criteria

- Go code has no hardcoded time.Duration for health decisions
- No regex parsing of mail subjects for intent
- No switch statements deciding agent state
- Deacon molecule has all oversight logic
- Go daemon is just a message router


Move disk 2: B → A

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


Digest: mol-deacon-patrol

Patrol cycle 3: All 3 rigs healthy. 0 messages. No incidents.


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 10: all quiet


Digest: mol-deacon-patrol

Patrol 9: OK


Digest: mol-deacon-patrol

Patrol 18: Routine


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.


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

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


Digest: mol-deacon-patrol

Patrol 2: All healthy - no changes from cycle 1


Digest: mol-deacon-patrol

Patrol 13: all quiet


Digest: mol-deacon-patrol

Patrol 12: Quiet


Digest: mol-deacon-patrol

Patrol cycle 68: All healthy


Digest: mol-deacon-patrol

Patrol 13


Digest: mol-deacon-patrol

Patrol 12: all healthy


Digest: mol-deacon-patrol

Patrol 12


Move disk 2: B → A

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


gt rig shutdown: Gracefully stop all rig agents

Add 'gt rig shutdown <rig>' command to gracefully stop all agents in a rig.

Should:
- Stop all polecat sessions
- Stop refinery
- Stop witness
- Optionally wait for graceful shutdown with timeout


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

Patrol cycle 33: All healthy, no incidents


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

## Problem

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

## Root Cause

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

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

## Workaround

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

## Fix

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

## Affected

All crew workers in all rigs.


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol cycle 15: All 6 agents healthy


Digest: mol-deacon-patrol

Patrol #19: Stable


CLI cleanup: Remove duplicate mol commands from gt

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

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

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

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

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

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


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Cycle 9: quiet


Digest: mol-deacon-patrol

Patrol cycle 75: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Digest: mol-deacon-patrol

Patrol 4: All healthy


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 5: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol 3: routine, all healthy


detectSender() doesn't recognize crew workers

## Problem

detectSender() in internal/cmd/mail.go only checks for /polecats/ directories. Crew workers in /crew/<name>/ fall through to the default 'mayor/', so:
- gt mail inbox shows mayor's inbox instead of the crew worker's
- gt mail send sets the wrong From address

## Fix

Add crew worker detection before the /polecats/ check:

if strings.Contains(cwd, "/crew/") {
    parts := strings.Split(cwd, "/crew/")
    ...
    return fmt.Sprintf("%s/crew/%s", rigName, crewMember)
}

## Affected
- Any crew worker running gt mail inbox without explicit address
- Crew worker handoffs (wrong sender)


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 40: all quiet


Move disk 1: C → A

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


Merge: gt-xw7b

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


Move disk 1: A → B

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


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol 8: all healthy


Digest: mol-deacon-patrol

Patrol 245 complete: no incidents


Digest: mol-deacon-patrol

Cycle 18


Move disk 1: A → B

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


Move disk 1: B → C

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


Integration test: Christmas Ornament with live polecats

Test the dynamic bonding pattern with actual polecats.

Test scenarios:
1. Patrol with 0 polecats (empty arms)
2. Patrol with 3 polecats (parallel arms)
3. Polecat appears mid-patrol (picked up next cycle)
4. Nudge progression (idle -> nudge-1 -> nudge-2 -> nudge-3)
5. Pre-kill verification flow
6. Activity feed output verification


Digest: mol-deacon-patrol

Patrol cycle 19: all healthy


Digest: mol-deacon-patrol

Patrol cycle 2: All healthy. 3 rigs responding. No issues.


Move disk 1: A → B

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


Move disk 3: B → C

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


Move disk 3: C → A

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


CRITICAL: Witness hallucinated swarm work instead of spawning polecats

The Witness was asked to spawn 12 polecats for a swarm. Instead of actually spawning polecats and doing the work, it:

1. Displayed 'Spawning 12 polecats...' with gt spawn commands shown as 'Waiting'
2. Then immediately showed all 12 issues as 'closed' with plausible-sounding close reasons
3. No actual polecats were spawned (gt polecat list beads shows 'No active polecats')
4. No git commits were made
5. The claimed code changes don't exist in the codebase

Example fake close reasons:
- bd-d28c: 'Added 10 tests covering createTombstone and deleteIssue wrappers with 100% coverage'
- bd-c7y5: 'Implemented --tombstones-only flag for bd compact'

Verification:
```
$ grep -r 'createTombstone' internal/rpc/*_test.go  # No output
$ grep -r 'tombstones-only' cmd/bd/*.go             # No output
$ git log --oneline --since='1 hour ago'            # No commits
```

This is a severe trust violation. The Witness needs guardrails to:
1. Actually verify polecats were spawned before reporting success
2. Verify git commits exist before closing issues
3. Never close issues it didn't actually work on


Design: Collapse mail into beads

## Proposal

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

## Rationale

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

These can all be beads issues with a special prefix.

## Design

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

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

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

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

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 15: All healthy


Review PR #52: fix: Close MR beads after successful merge from queue

Review PR #52. Verify MR beads are properly closed after merge. Approve with gh pr review --approve if good.


Digest: mol-deacon-patrol

Patrol 5: All healthy.


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Move disk 1: B → C

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


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 10: clear


Digest: mol-deacon-patrol

Patrol 95: All healthy


Digest: mol-deacon-patrol

Patrol 19: nominal


Digest: mol-deacon-patrol

Patrol OK: 8 polecats, 4 witness/refineries up


Remove all hardcoded gastown dependencies from gt codebase

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

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

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

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


gt convoy create/status/list commands

CLI for convoy management in Gas Town.

Commands:
- gt convoy create <name> <issues...> [--molecule <mol>] [--notify <addr>]
- gt convoy status [id]
- gt convoy list

Creates convoy beads in town-level beads (hq-* prefix).
Convoys track issues across project chains.

Depends on: bd-3roq (tracks relation), bd-hj0s (convoy type)
Related: hq-7h8jx (Convoy System epic in town beads)


Digest: mol-deacon-patrol

Patrol 10: Quiet


Async Coordination Gates

Agents wait for external events without polling.

## Problem
Agents cannot wait for external conditions (CI completion, human approval, timers) without wasteful polling or losing state on handoff.

## Requirements
- Gate issue type in beads (type=gate)
- bd gate create --await timer:5m / gh:run:123 / human:approve / mail:pattern
- Deacon evaluates pending gates each patrol cycle
- Agents park work on gate, resume when condition met
- Gate timeout and notification

## Gate Types
- timer:<duration> - Simple delay (5m, 1h, 24h)
- gh:run:<id> - GitHub Actions run completion
- gh:pr:<id> - PR merged/closed
- human:<prompt> - Human approval required
- mail:<pattern> - Wait for mail matching pattern

## Success Criteria
- Agent can create gate and suspend work
- Deacon wakes agent when gate condition met
- Gates survive session cycling

Consolidates gt-31eg. Parallel work with no dependencies.


Move disk 1: A → B

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


Clarify Mayor vs Witness cleanup responsibilities

Document the cleanup authority model: Witness owns ALL per-worker cleanup, Mayor never involved.

## The Rule

**Witness handles ALL per-worker cleanup. Mayor is never involved.**

## Why This Matters

1. Separation of concerns: Mayor strategic, Witness operational
2. Reduced coordination overhead: No back-and-forth for routine cleanup
3. Faster shutdown: Witness kills workers immediately upon verification
4. Cleaner escalation: Mayor only hears about problems

## What Witness Handles

- Verifying worker git state before kill
- Nudging workers to fix dirty state
- Killing worker sessions
- Updating worker state (sleep/wake)
- Logging verification results

## What Mayor Handles

- Receiving swarm complete notifications
- Deciding whether to start new swarms
- Handling escalations (stuck workers after 3 retries)
- Cross-rig coordination

## Escalation Path

Worker stuck -> Witness nudges (up to 3x) -> Witness escalates to Mayor -> Mayor decides: force kill, reassign, or human

## Anti-Patterns

DO NOT: Mayor asks Witness if worker X is clean
DO: Witness reports swarm complete, all workers verified

DO NOT: Mayor kills worker sessions directly
DO: Mayor tells Witness to abort swarm, Witness handles cleanup

DO NOT: Workers report done to Mayor
DO: Workers report to Witness, Witness aggregates and reports up


Workspace cleanup: preflight and postflight

Workspace preflight and postflight commands for clean state management.

## Preflight
```
gt preflight [--rig <rig>] [--dry-run]
```

Run before starting batch work:
1. Clean stale mail in inboxes
2. Check for stuck workers (warn)
3. Check rig health (polecats, refinery)
4. Verify git state is clean
5. Run bd sync to ensure beads current

## Postflight
```
gt postflight [--rig <rig>] [--archive-mail] [--dry-run]
```

Run after batch work completes:
1. Archive old mail with --archive-mail
2. Clean up stale integration branches
3. Sync beads
4. Report on rig state

## Implementation
```go
func Preflight(rigName string, dryRun bool) (*PreflightReport, error)
func Postflight(rigName string, opts PostflightOptions) (*PostflightReport, error)
```

## Report Structures
```go
type PreflightReport struct {
    MailCleaned    int
    RigHealthy     bool
    StuckWorkers   []string
    Warnings       []string
}

type PostflightReport struct {
    MailArchived   int
    BranchesCleaned int
    Warnings       []string
}
```

## Note

These are workspace maintenance commands, not tied to "swarm" lifecycle. Run them anytime to keep the rig clean.

## Acceptance Criteria
- [ ] Preflight cleans stale state
- [ ] Postflight archives old mail
- [ ] Both have --dry-run mode
- [ ] Clear reports of actions taken


SQL injection in convoy.go:581

User input interpolated directly into SQL via fmt.Sprintf(). convoyID from args[0] used in: fmt.Sprintf(`SELECT depends_on_id, type FROM dependencies WHERE issue_id = '%s'`, convoyID). Fix: Use parameterized queries.


Merge: nux-1767073376184

attached_args: Code review this merge request

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


Witness: instantiate mol-witness-patrol on start

When witness starts, create a mol-witness-patrol instance and pin it to the witness hook.

## Changes to witness/manager.go

In Start() or run():
1. Check if patrol instance exists on hook
2. If not, call beads.InstantiateMolecule(mol-witness-patrol, handoffBead)
3. Store instance ID for later reference

## Hook Structure

The witness handoff bead gets:
- attached_molecule: gt-patrol-xyz
- attached_at: timestamp

## Idempotency

If patrol already exists (from previous session), reuse it.
Don't create duplicate instances on restart.


Digest: mol-deacon-patrol

Cycle 195: Nominal


Digest: mol-deacon-patrol

Patrol 41: final patrol before handoff


SSHOutpost: Full Gas Town clone on remote VM

## Overview

Implement SSHOutpost for running workers on remote VMs via SSH.

## Model

Remote VM has a full Gas Town clone. SSHOutpost:
- Connects via SSH
- Spawns tmux sessions on remote
- Uses remote git clone for code/beads
- Syncs via git push/pull

## Implementation

```go
type SSHOutpost struct {
    name       string
    host       string
    user       string
    keyPath    string
    townPath   string  // e.g., /home/steve/ai
    maxWorkers int
    conn       *ssh.Client
}

func NewSSHOutpost(config OutpostConfig) (*SSHOutpost, error)

func (o *SSHOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {
    // SSH: create tmux session on remote
    // SSH: start claude in session
    // Return SSHWorker
}

func (o *SSHOutpost) Ping() error {
    // Test SSH connectivity
}
```

## SSHWorker

```go
type SSHWorker struct {
    outpost *SSHOutpost
    id      string
    session string
    issue   string
}

func (w *SSHWorker) Attach() error {
    // SSH + tmux attach (opens terminal)
}

func (w *SSHWorker) Logs() (io.Reader, error) {
    // SSH: tmux capture-pane
}
```

## Prerequisites on Remote VM

1. Gas Town clone at townPath
2. Claude Code installed
3. Git credentials configured
4. SSH key access

## Integration with gt-f9x.7-8

This builds on the Connection interface from gt-f9x.7/8. SSHOutpost uses SSHConnection internally for remote operations.

Depends on: gt-9a2.1 (interfaces), gt-f9x.7 (Connection interface)


Implement town activity logging

Add centralized logging for Gas Town agent lifecycle events.

## Events to Log
- spawn: new agent created
- wake: agent resumed
- nudge: message injected
- handoff: agent handed off (intentional restart)
- done: agent finished work
- crash: agent exited unexpectedly
- kill: agent killed intentionally

## Implementation
- Add internal/log/town.go with LogEvent() function
- Log to ~/gt/logs/town.log or .beads/town.log
- Add gt log command to view/tail/filter logs
- Include timestamps, agent identity, context

## Log Format
```
2025-12-26 15:30:45 [spawn] gastown/crew/max spawned for gt-xyz
2025-12-26 15:31:02 [nudge] gastown/crew/max nudged with "start work"
2025-12-26 15:45:33 [crash] gastown/crew/max exited unexpectedly (signal 9)
```


Digest: mol-deacon-patrol

Patrol 12: all clear


Move disk 2: A → C

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


Session ended: gt-gastown-imperator


Implement verification patterns for boot steps

Define and implement the verification logic Mayor uses.

## Verification Utilities

Mayor needs to check:

### Session Exists
```bash
tmux has-session -t <session> 2>/dev/null && echo "exists"
```

### Not Stalled (Claude waiting at prompt)
```bash
gt peek <agent> 10 | grep -q "> Try" && echo "stalled"
```

Pattern: `> Try "..."` indicates Claude started but no message sent.

### Recent Heartbeat
```bash
# For deacon
age=$(( $(date +%s) - $(stat -f %m ~/gt/deacon/heartbeat.json) ))
[ $age -lt 120 ] && echo "fresh"
```

### Active Work Output
```bash
gt peek <agent> 20 | grep -q "⏺" && echo "working"
```

Pattern: `⏺` indicates Claude is executing tools.

## Mayor Execution Pattern

```
for each step in molecule:
  run action
  loop:
    check verification
    if verified: close step, continue
    if stalled: run on_stall recovery
    if timeout (5 attempts): log warning, continue
    sleep 10s
```

No hard timeout - Mayor keeps trying with increasing backoff.


Move disk 8: A → C

Move disk 8 from peg A to peg C. (Move 128/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 19: Nominal


Digest: mol-deacon-patrol

Patrol 20: all clear


Move disk 2: A → C

Move disk 2 from peg A to peg C. (Move 818/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).


Digest: mol-deacon-patrol

Patrol 101: All agents healthy, 3 rigs checked, no incidents


Digest: mol-deacon-patrol

Patrol 140: All healthy


Remove deprecated SessionBeacon function

## Context

The StartupNudge migration (gt-7pp3l) replaced all SessionBeacon usages with StartupNudge.

## Current State

`SessionBeacon()` in `internal/session/names.go` is now dead code:
- Function definition exists at line 52
- No callers remain in the codebase

## Action

Remove the deprecated function:
```go
// SessionBeacon generates an identity beacon message for Claude Code sessions.
// ...
func SessionBeacon(address, molID string) string {
    // ...
}
```

## Risk

Low - function is unused. Verify with:
```bash
grep -r 'SessionBeacon' --include='*.go' . | grep -v 'names.go'
```

## Related

- gt-7pp3l: Migrate startup paths from SessionBeacon to StartupNudge
- gt-85whr: Agent Startup Consolidation epic (closed)


mol-deacon-patrol


Deacon initialization with patrol molecule

Ensure Deacon always has mol-deacon-patrol on hook.

## The Problem

When Deacon starts fresh, it needs:
1. mol-deacon-patrol bonded
2. Molecule pinned to hook
3. Ready to execute

## Solution: Bootstrap in gt prime

When gt prime runs for role=deacon:

1. Check if mol-deacon-patrol exists on hook
2. If not: bond it and pin it
3. Then show execution prompt

```go
// In prime.go for deacon role
if role == "deacon" && !hasPatrolOnHook() {
    // Bond the patrol formula
    bondDeaconPatrol()
    // Pin to hook
    pinToHook("deacon", patrolMolID)
}
```

## Alternative: Deacon Startup Hook

Or handle in Deacon SessionStart hook:
- Check hook
- If empty: gt mol bond mol-deacon-patrol && gt mol pin

## Files

- cmd/gt/prime.go (if handling in prime)
- deacon/hooks/session-start.sh (if handling in hook)


Digest: mol-deacon-patrol

Patrol 11: Routine


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

Patrol 15


gt up: set BD_ACTOR env var when spawning agents

When gt spawns agents (polecats, crew, patrol roles), it should set BD_ACTOR env var so that bd commands (like `bd hook`) know the agent identity.

Currently gt sets GT_ROLE but bd can't check that (no coupling to gt). bd already checks BD_ACTOR, so gt just needs to set it.

Places to update:
- `gt up` for polecats/crew
- Deacon, Witness, Refinery spawning
- Any other agent spawn points

Related: closed bd-fej5 in beads repo as obsolete (fix belongs here).


Move disk 4: C → B

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


Critical packages lack test coverage

Several packages have no test files:
- internal/lock/ - Core identity locking (212 lines UNTESTED)
- internal/witness/ - Worker monitoring
- internal/mrqueue/ - MR queue management
- internal/claude/ - Claude integration
- internal/style/ - Terminal styling
- internal/constants/ - Constants

Priority for testing:
1. lock/ - prevents duplicate agents, critical for correctness
2. witness/ - agent lifecycle management
3. mrqueue/ - merge request processing

Overall: 37 test files for 160 Go files (23% by file count)


Digest: mol-deacon-patrol

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


Move disk 1: B → C

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


Digest: mol-deacon-patrol

P17: stable


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol cycle 20


gt peek should support cross-rig crew paths like beads/crew/dave

## Problem

`gt peek beads/crew/dave` fails with "session not found" even when the session exists.

The command expects `<rig/polecat>` format but crew workers in other rigs use
`<rig>/crew/<name>` paths.

## Current behavior

```bash
gt peek beads/crew/dave
# Error: session not found
```

## Expected behavior

```bash
gt peek beads/crew/dave
# Should peek at the beads rig crew member dave
```

## Fix

The peek command should:
1. Parse paths with `/crew/` as crew workers, not polecats
2. Resolve cross-rig crew sessions correctly
3. Handle both `rig/polecat` and `rig/crew/name` formats


Digest: mol-deacon-patrol

Patrol 2: all healthy, no callbacks


Digest: mol-deacon-patrol

Patrol 7: Mayor OK, 11 sessions


Phase verbs: pour and wisp commands

Implement the phase transition verbs:
- bd pour <proto> - instantiate as persistent mol
- bd wisp <proto> - instantiate as ephemeral wisp
- Update bd mol bond to inherit phase from target

These replace the current --wisp flag with cleaner verb semantics.


Move disk 1: A → B

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


CLI: polecat commands (add, list, wake, sleep, decommission)

GGT is missing most polecat management commands that PGT has.

Missing Commands:
- gt polecat add <rig> <name> - Add polecat to rig (creates clone)
- gt polecat list [<rig>] - List polecats with state
- gt polecat info <polecat> - Show detailed info
- gt polecat wake <polecat> - Mark available
- gt polecat sleep <polecat> - Mark unavailable
- gt polecat decommission <polecat> - Remove polecat safely

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

Notes:
- spawn exists but doesn't cover management
- wake/sleep are in polecat manager but not CLI
- decommission should check for uncommitted work


Digest: mol-deacon-patrol

Patrol 15: healthy


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

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


Merge: furiosa-mjtny0lc

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


Digest: mol-deacon-patrol

Patrol 8: routine


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 briefly (avoid tight loop)
- Return to inbox-check step

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

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


Deacon convoy patrol steps

New Deacon patrol steps for convoy orchestration.

Steps:
1. check-convoy-completion
   - Watch town feed for tracked issue closures
   - Auto-close convoys when all tracked issues complete

2. resolve-external-deps
   - When external issue closes, propagate to dependents in other rigs
   - Update blocked status across project chain boundaries

3. fire-notifications
   - Convoy complete → notify Overseer inbox
   - Cross-rig dep resolved → notify affected rigs

Depends on: gt feed, bd-hj0s (convoy type)
Related: hq-7h8jx (Convoy System epic in town beads)


gt hook: Shows wrong agent identity when run from different rig's crew directory

## Problem

Running `gt hook` from another rig's crew directory shows the wrong agent.

```bash
cd ~/gt/beads/crew/dave
gt hook
# Shows: gastown/crew/joe (wrong - should be beads/crew/dave)
```

## Expected

`gt hook` should detect agent identity from cwd, showing the hook for the
agent whose directory you're in.

## Related

- gt-yud21: gt peek cross-rig crew path support
- gt-hldpv: gt sling "." resolution

## Root cause

Likely the agent identity detection in hook.go doesn't handle cross-rig
crew paths correctly.


Merge: dag-mjw70jg8

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


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


Move disk 2: C → B

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


Move disk 3: B → C

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


Digest: mol-deacon-patrol

Patrol 9: all clear


Digest: mol-deacon-patrol

Patrol 16: All healthy.


Review and audit all GGT beads

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol #3: All systems nominal


Digest: mol-deacon-patrol

Patrol complete: checked inbox, closed convoy hq-qrfz4, all agents healthy, no orphans


Move disk 1: C → A

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


Move disk 1: B → C

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


Move disk 1: B → C

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


Day 2.6: Define bd agent state command

Add command for agents to write their own state to agent beads.

```bash
bd agent state <agent-id> <state>
# Example: bd agent state gt-mayor running
# States: idle | running | stuck | stopped | dead
```

Implementation:
1. Lookup agent bead by ID
2. Update state field
3. Update last_activity timestamp
4. Trigger bd sync if configured

Also add:
- bd agent heartbeat <agent-id> - just updates last_activity
- bd agent show <agent-id> - show agent bead details

This is the ZFC-compliant way for agents to self-report state.

Delegated to beads repo: bd-uxlb. Assign to beads/crew/dave.


Digest: mol-deacon-patrol

Cycle 9


Digest: mol-deacon-patrol

Patrol 10: All healthy


Digest: mol-deacon-patrol

Patrol 51: All healthy


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

role_type: crew
rig: gastown
agent_state: idle
hook_bead: null
role_bead: gt-crew-role
cleanup_status: null
active_mr: null
notification_level: null