Polecat Mood Plugin (standard)

Standard witness plugin molecule that assesses polecat emotional state.

## Molecule Definition

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

## Mood Emojis

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

## Bonding

During witness patrol plugin-run step:

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

## Installation

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

## Customization

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


Digest: mol-deacon-patrol

Patrol cycle 4: All quiet.


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

Patrol 1: All healthy, no actions


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.


Track spawned sessions in DogDispatchInfo

Minor TODO in internal/cmd/sling.go:1002:

```go
return &DogDispatchInfo{
    DogName:  targetDog.Name,
    AgentID:  agentID,
    Pane:     pane,
    Spawned:  false, // TODO: track if we spawned a new session
}, nil
```

The Spawned field is always false. Should track if DispatchToDog actually spawned a new session vs reused an existing one.

Low priority - the information could be useful for logging/debugging but doesn't affect functionality.


Digest: mol-deacon-patrol

Patrol 155: All healthy


Refinery: Send MERGED notification to witness after merge

During liftoff test (gt-j0gx2), observed that refinery:
1. Received MERGE_READY for nux
2. Fetched, rebased, resolved conflicts correctly
3. Ran tests (passed)
4. Merged to main and pushed
5. Deleted polecat branch

But did NOT:
- Send MERGED mail to witness
- Close the MR bead (gt-5qkah)

The mol-refinery-patrol.formula.toml documents this step but the agent didn't execute it.

Impact:
- Witness never receives MERGED signal
- Polecat worktree never gets nuked
- MR beads accumulate as open

Fix:
After successful merge+push, refinery must:
```bash
gt mail send <rig>/witness -s "MERGED <polecat>" -m "..."
bd close <mr-bead> --reason "Merged to main"
```


Move disk 1: C → A

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


Move disk 4: B → A

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


Digest: mol-deacon-patrol

Patrol 9: all healthy


Update docs with molecule navigation workflow

Update architecture and workflow docs with new molecule navigation.

## Docs to update

### docs/molecules.md
- Add 'Navigating Molecules' section
- Document bd mol current usage
- Document bd close --continue workflow
- Show the propulsion pattern

### docs/propulsion-principle.md
- Add molecule navigation as key enabler
- Show before/after workflow comparison

### docs/polecat-wisp-architecture.md
- Update step execution section
- Show bd close --continue in examples

## New section content

### Molecule Navigation

Finding your place:
  bd mol current              # Where am I?
  bd mol current gt-abc       # Status of specific molecule

Seamless transitions:
  bd close gt-abc.3 --continue   # Close and advance
  bd close gt-abc.3 --no-auto    # Close but don't auto-claim next

The old way (3 commands):
  bd close gt-abc.3
  bd ready --parent=gt-abc
  bd update gt-abc.4 --status=in_progress

The new way (1 command):
  bd close gt-abc.3 --continue

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


Digest: mol-deacon-patrol

Patrol cycle 63: All healthy


Refinery not processing merge-requests - stale MRs accumulating

Discovered 15 stale merge-request issues in beads rig that were never processed by the refinery. These appear to be from polecat branches that completed work but the refinery didn't pick up the merge-requests.

Closed issues:
- bd-r06v, bd-bhg7, bd-754r, bd-fcl1, bd-3zzh
- bd-bijf, bd-5rj1, bd-kptp, bd-rdzk, bd-ibl9
- bd-gfo3, bd-aq3s, bd-x2bd, bd-s1pz, bd-h27p

Need to investigate:
1. Why refinery isn't picking up merge-requests
2. Whether the polecat branches have valid work to merge
3. Add monitoring/alerting for stale MRs


Digest: mol-deacon-patrol

Patrol 2: All healthy, fixed 1 stale lock


Move disk 1: C → A

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


Move disk 1: A → B

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


Move disk 1: A → B

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


gt-polecat-gastown-capable

gt-polecat-gastown-capable

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


Digest: mol-deacon-patrol

Patrol 6: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol 20: All healthy, 2 crew active


mol-deacon-patrol


Move disk 1: C → A

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


Work assignment messages should auto-close on completion

When a polecat completes work on an issue, the work assignment message (msg-type:task) stays open. Found 7 stale work assignments in gastown after swarm completed.

Proposal: When bd close is called on an issue, auto-close any work assignment messages that reference that issue in their body.

Alternative: Work assignment messages could use a different lifecycle - perhaps they should be acked (closed) when the polecat starts working, not when they finish.


Digest: mol-deacon-patrol

Patrol 4: quiet


Digest: mol-deacon-patrol

Patrol cycle 62: All healthy, no issues


Digest: mol-deacon-patrol

Patrol cycle 44: All healthy


Merge: gt-g44u.3

branch: polecat/Ace
target: main
source_issue: gt-g44u.3
rig: gastown


Digest: mol-deacon-patrol

Patrol 15: all healthy, doctor pass


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Cycle 187: Nominal


Merge: slit-mjvtz18y

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


Day 3.0: Document mail protocol for patrol coordination

Document the mail protocol used for patrol coordination.

**Mail types:**
- POLECAT_DONE: Polecat → Witness (work complete, ready for merge)
- MERGE_READY: Witness → Refinery (branch ready for merge queue)
- MERGED: Refinery → Witness (merge complete, safe to nuke)
- WITNESS_PING: Witness → Deacon (health check for second-order monitoring)
- HELP: Any → escalation target (stuck, need intervention)
- HANDOFF: Any → self (session continuity)

**Format conventions:**
- Subject prefix indicates type (e.g., 'POLECAT_DONE: nux')
- Body contains structured data (branch, bead ID, etc.)

This documentation enables consistent implementation across all patrol formulas.


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Idle Town Principle

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

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

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

## Second-Order Monitoring

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

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


Move disk 3: C → A

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


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

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


Digest: mol-deacon-patrol

Patrol 8: healthy


gt dog add/remove/list/call/status CLI

Dog management commands:
- gt dog add <name> - Create dog in kennel with multi-rig worktrees
- gt dog remove <name> - Retire dog, cleanup worktrees
- gt dog list - Show the pack (all dogs with status)
- gt dog call [name] - Wake idle dog(s)
- gt dog status [name] - Show detailed dog state


Digest: mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol #19


Digest: mol-deacon-patrol

Patrol 15: Nominal


mol-deacon-patrol


Add gt seance command for predecessor discovery

## Purpose

**"Where did you put the stuff you left for me?"** - The #1 question in any handoff.

Seance lets you literally talk to your predecessor. Not parse their logs - commune with them.

## The Insight

Claude Code can resume sessions with full context. A seance spawns a Claude subprocess that resumes a predecessor session, letting you ask questions directly:
- "Why did you make this decision?"
- "Where were you stuck?"
- "What did you try that did not work?"

## Architecture

```
gt seance --talk <session-id>
    │
    └─▶ claude --fork-session --resume <id>
        │
        └─▶ Spawns in sandbox namespace (ghost-joe)
            │
            └─▶ Communication via tmux
                "Where is the config you mentioned?"
                → Predecessor has full context, answers
```

**Key flags:**
- `--fork-session` creates new session ID (read-only seance, no grave disturbance)
- `--resume <id>` loads predecessor context

## Discovery

Sessions are discoverable via:
1. **Beacon in transcript** - `[GAS TOWN] role • topic • timestamp` searchable via `/resume`
2. **SessionStart events** - Hook emits to `~/gt/.events.jsonl` (our data, ZFC-compliant)
3. **Claude /resume search** - Native filtering

## Usage

```bash
gt seance                     # List discoverable sessions
gt seance --role crew         # Filter by role
gt seance --rig gastown       # Filter by rig
gt seance --recent 10         # Last N sessions

gt seance --talk <id>         # THE SEANCE - talk to predecessor
gt seance --talk <id> -p "Where is X?"  # One-shot question
```

## ZFC Compliance

- **No parsing Claude internals** - Use Claude CLI to resume
- **Agent discovers** - Claude reads session, interprets, responds
- **Events are ours** - SessionStart hook writes to our event stream

## Beacon Format

```
[GAS TOWN] gastown/crew/joe <- deacon • 2025-12-30T15:42 • assigned:gt-xyz
```

Searchable via `claude --resume "GAS TOWN"` or `claude --resume "gastown/crew/joe"`


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

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


Molecular Chemistry Cleanup: Fix inaccurate molecule depictions

## The Correct Model

According to molecular-chemistry.md, the hierarchy is:

Formula (YAML DSL) --cook--> Proto (template beads) --pour/wisp--> Mol/Wisp (actual work)

- **Formulas**: YAML files in .beads/formulas/ that define workflow structure
- **Cook**: Transform formula to proto beads (with [template] label)
- **Proto**: Template beads with child beads for each step
- **Pour**: Proto to Mol (persistent liquid)
- **Wisp**: Proto to Wisp (ephemeral vapor)

## What's Wrong

We have legacy code and docs that use the OLD model where molecules are defined
in Go code as structs with embedded markdown, instead of as formula YAML cooked into proto beads.

---

## MAJOR ISSUES

### 1. Go Code: molecules_*.go (DELETE OR REWRITE)

**Files:**
- internal/beads/builtin_molecules.go
- internal/beads/molecules_patrol.go (19KB!)
- internal/beads/molecules_session.go (13KB)
- internal/beads/molecules_work.go (13KB)

**Problem:** Defines molecules as Go structs with embedded markdown descriptions.
This is completely wrong. Molecules should come from:
1. Formula YAML files cooked into proto beads
2. Proto beads with child beads for each step

**Used by:**
- install.go:seedBuiltinMolecules() - seeds during install
- catalog.go - includes in catalog
- molecule_list.go:ExportBuiltinMolecules()

**Fix:** Delete these files. Create formula YAML files instead. Update seeding
to cook formulas into protos.

### 2. Role Templates: Steps Listed in Markdown (REWRITE)

**Files:**
- prompts/roles/deacon.md - Lists 7 patrol steps
- prompts/roles/refinery.md - Lists 10 patrol steps
- prompts/roles/witness.md - Procedural "Heartbeat Protocol" (not molecule-based!)
- prompts/roles/polecat.md - References molecule steps

**Problem:** The steps are listed in the markdown template, but they should be
discovered from the proto beads via bd mol current. Templates should say
"check your hook, run your patrol" without duplicating step definitions.

**Fix:** Templates should describe HOW to run a patrol (propulsion principle,
bd mol current, bd close --continue), not WHAT the steps are.

### 3. Protos are Empty/Missing (CREATE)

**Current state:**
- gt-iep9 (mol-deacon-patrol) - Only 2 child steps
- gt-qflq (mol-witness-patrol) - EMPTY (0 children)
- mol-refinery-patrol - DOESN'T EXIST

**Fix:** Create formula YAML files for each patrol, cook them into proper protos
with child beads for each step.

---

## MEDIUM ISSUES

### 4. Command Confusion: spawn vs pour/wisp

**Files:**
- prompts/roles/deacon.md - Uses bd mol spawn ... --assignee=deacon
- prompts/roles/refinery.md - Uses bd mol spawn ... --wisp
- Various docs

**Problem:** The correct commands per molecular-chemistry.md:
- bd pour proto - Create persistent mol (liquid)
- bd wisp proto - Create ephemeral wisp (vapor)
- bd mol spawn - Old/deprecated

**Fix:** Update all references to use bd wisp for patrols, bd pour for
persistent work.

### 5. Command Confusion: gt mol vs bd mol

**Files:** Various docs and templates

**Problem:** Some use gt mol status, others bd mol status. Need to clarify:
- gt mol = Gas Town wrapper (if it exists, what does it add?)
- bd mol = Beads molecule commands (authoritative)

**Fix:** Audit and standardize. If gt mol is a thin wrapper, remove it.

### 6. polecat-wisp-architecture.md (UPDATE OR DELETE)

**File:** docs/polecat-wisp-architecture.md

**Problem:** References adding molecules to builtin_molecules.go - old model.

### 7. manager.go (UPDATE)

**File:** internal/rig/manager.go

**Problem:** Comment references "subset of builtin_molecules.go for seeding"

---

## IMPLEMENTATION ORDER

1. **Create formula YAML files** for the 3 patrol molecules:
   - mol-deacon-patrol.formula.yaml
   - mol-witness-patrol.formula.yaml
   - mol-refinery-patrol.formula.yaml

2. **Implement bd cook** if not already working to create protos from formulas

3. **Cook the formulas** into proto beads with proper child beads

4. **Update role templates** to use propulsion principle without step lists

5. **Delete molecules_*.go** once formulas are working

6. **Update install.go** to cook formulas instead of seeding Go structs

7. **Audit gt mol vs bd mol** and standardize


Digest: mol-deacon-patrol

Patrol 6: OK


Move disk 4: A → C

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


Digest: mol-deacon-patrol

Patrol 5: All clear


implement

Implement the solution for gt-test123. 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


Move disk 2: B → A

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


Digest: mol-deacon-patrol

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


CLI: plugin commands (list, status)

Add gt plugins <rig> to list plugins and gt plugin status <name> to check plugin state. Simple directory scan of <rig>/plugins/.


Deacon patrol banners: visual feedback on atom transitions

Print large ASCII banners when transitioning between patrol atoms.

## Problem

When the deacon progresses through patrol atoms (steps), there is no visual feedback.
The operator cannot easily see what the deacon is doing without reading the full output.

## Desired Behavior

Print banners on step start and completion:

  INBOX-CHECK - Checking for lifecycle requests, escalations, timers
  INBOX-CHECK COMPLETE - Processed 3 messages, 0 lifecycle requests

## Benefits

1. Scanability: Operator can glance at tmux and see what is happening
2. Progress tracking: Easy to see where in the patrol loop we are
3. Debugging: Clear demarcation between steps for troubleshooting

## Implementation Options

1. In deacon CLAUDE.md: Instruct agent to print banners
2. gt patrol step start/end: Commands that print banners
3. bd mol step hooks: Automatically on step transitions

## Related

- gt-id36: Deacon Kernel
- gt-rana: Patrol System


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 4: routine


Witness events in gt feed

Wire witness patrol events to gt feed display.

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

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


Formula Molecules: Guzzoline production for Gas Town

## Vision

Gas Town executes work. But it also needs to PRODUCE work - structured, high-quality guzzoline on demand. **Formula Molecules** are recipes that spawn structured convoys.

## Core Insight

A formula is a molecule template that:
1. Takes input (a PR, a design problem, a codebase)
2. Spawns multiple polecats with specific focuses
3. Each leg produces structured output
4. Synthesis step combines into unified deliverable

Gas Town becomes both consumer AND producer of guzzoline.

## Example Formulas

### Design Convoy Formula
Input: Feature request or problem statement
Legs (parallel):
- API design polecat
- Data model polecat
- UX/ergonomics polecat
- Scalability polecat
- Security polecat
Synthesis: Unified design doc with tradeoffs

### Code Review Convoy Formula
Input: PR or file set
Legs (parallel):
- Correctness: Does it work?
- Performance: Any bottlenecks?
- Security: Vulnerabilities?
- Elegance: Clean design?
- Resilience: Error handling?
- Style: Convention compliance?
- Smells: Anti-patterns?
- Legacy: Respects existing patterns?
Synthesis: Categorized review with priority issues

### Other Formula Ideas
- Test Coverage Convoy: Unit, integration, edge cases, error paths
- Documentation Convoy: API docs, user guide, examples, changelog
- Migration Convoy: Database, API, config, rollback plan
- Incident Response: Root cause, timeline, fix, prevention

## Mol Mall

Library/marketplace of formulas:
```bash
gt formula list              # Available formulas
gt formula show code-review  # Formula details
gt formula run code-review --pr=123  # Execute formula → convoy
gt formula create my-review  # Create custom formula
```

## Technical Design

### Formula Structure (in beads)
```yaml
id: formula-code-review
type: formula
name: Code Review
inputs:
  - name: target
    type: pr | files | branch
legs:
  - name: correctness
    focus: "Verify logical correctness and edge cases"
    output: findings.md
  - name: security
    focus: "Identify security vulnerabilities"
    output: findings.md
  # ...
synthesis:
  inputs: all leg outputs
  output: review-summary.md
```

### Execution Model
1. `gt formula run` creates convoy with formula reference
2. Spawns polecats for each leg (parallel where possible)
3. Each polecat gets leg-specific prompt + shared context
4. Outputs collected as bead attachments or slots
5. Synthesis polecat reads all outputs, produces final deliverable
6. Convoy lands with unified result

### Dependencies
- Leg outputs feed synthesis (internal convoy deps)
- Formula can specify leg ordering if needed
- Parallel by default, sequential where required

## Open Questions

1. Where do formulas live? Town-level beads? Separate formula registry?
2. How to version/share formulas across towns?
3. Leg output format standardization?
4. Human checkpoints between legs or only at end?
5. Partial formula runs (skip some legs)?
6. Formula composition (formula that includes other formulas)?

## Why This Matters

Gas Town currently waits for humans to create work. With formulas:
- Mayor can invoke structured reviews on any PR
- Design work follows consistent methodology
- Quality processes are repeatable and scalable
- Work generation becomes as automated as work execution

**Guzzoline factory, not just guzzoline consumer.**


Rollback support: gt mq revert for problematic merges

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

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

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

Track revert in MR metadata for audit trail.

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


Digest: mol-deacon-patrol

Patrol 47: All healthy


ensure-deacon

Start the Deacon and verify patrol mode is active.

## Action
```bash
gt deacon start
```

## Verify
1. Session exists: `tmux has-session -t gt-deacon 2>/dev/null`
2. Not stalled: `gt peek deacon/` does NOT show "> Try" prompt
3. Heartbeat fresh: `deacon/heartbeat.json` modified < 2 min ago

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

## OnFail
Log error and continue - town can run with degraded deacon.
The Witness can still manage polecats without Deacon oversight.


Fix docs: Formulas are JSON not YAML

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


Daemon: integration test with real lifecycle

Need an end-to-end test that:
1. Starts daemon
2. Starts a test agent session
3. Sends lifecycle request to daemon
4. Verifies session was killed and restarted
5. Cleans up

Could use a mock 'agent' that's just a shell script.


Digest: mol-deacon-patrol

Patrol cycle 15: all healthy


Digest: mol-deacon-patrol

Patrol 10: healthy


Digest: mol-deacon-patrol

Patrol 14: all clear


Digest: mol-deacon-patrol

Patrol 19


Digest: mol-deacon-patrol

Patrol 6: all quiet


Move disk 1: C → A

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol cycle 6: All agents healthy


Digest: mol-deacon-patrol

Patrol cycle 20: All 6 agents healthy, 4 polecats active, no orphans, inbox clean


Digest: mol-deacon-patrol

Patrol 12: Quick cycle, all quiet


Document Rig/Cook/Run lifecycle

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


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

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

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

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

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

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


VM outpost setup: Terraform and documentation

## Overview

Documentation and optional Terraform for setting up VM outposts.

## Manual Setup Guide

```markdown
# Setting Up a VM Outpost

## Prerequisites
- GCE VM (or any Linux machine with SSH access)
- SSH key pair
- Git configured on VM

## Steps

1. Install Claude Code on VM:
   ```bash
   ssh user@vm
   npm install -g @anthropic-ai/claude-code
   ```

2. Clone Gas Town:
   ```bash
   mkdir -p ~/ai
   cd ~/ai
   gt install .
   ```

3. Configure Git credentials:
   ```bash
   git config --global user.name "Your Name"
   git config --global credential.helper store
   ```

4. Add outpost to local config:
   ```bash
   gt outpost add ssh \
     --name gce-burst \
     --host 10.0.0.5 \
     --user steve \
     --key ~/.ssh/gce_worker \
     --town-path /home/steve/ai \
     --max-workers 8
   ```

5. Test connectivity:
   ```bash
   gt outpost ping gce-burst
   ```
```

## Terraform Module (Optional)

```hcl
# deploy/terraform/vm-outpost/main.tf

variable "project" {}
variable "zone" { default = "us-central1-a" }
variable "machine_type" { default = "e2-standard-4" }

resource "google_compute_instance" "outpost" {
  name         = "gastown-outpost"
  machine_type = var.machine_type
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "ubuntu-2204-lts"
      size  = 100
    }
  }

  network_interface {
    network = "default"
    access_config {}
  }

  metadata_startup_script = file("${path.module}/startup.sh")
}

output "external_ip" {
  value = google_compute_instance.outpost.network_interface[0].access_config[0].nat_ip
}
```

## Files

- `docs/vm-outpost-setup.md`
- `deploy/terraform/vm-outpost/` (optional)

Depends on: gt-9a2.5 (SSHOutpost)


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Idle Town Principle

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

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

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

## Second-Order Monitoring

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

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


Move disk 2: C → B

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


Generate handoff summary

Summarize this patrol cycle for digest.

Include:
- Workers inspected (count, names)
- Nudges sent (count, to whom)
- Sessions killed (count, names)
- Escalations (count, issues)
- Issues found (brief descriptions)
- Actions pending for next cycle

This becomes the digest when the patrol wisp is squashed.


Move disk 3: A → B

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


Digest: mol-deacon-patrol

Patrol 8: quiet


test-agent-verify


Digest: mol-deacon-patrol

Patrol 12: All green


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 16: All healthy


Witness session startup (gt witness start)

Implement gt witness start <rig>

Should:
1. Verify rig exists and has witness/ directory
2. Check for existing witness session (don't double-start)
3. Create tmux session: gt-<rig>-witness
4. Start Claude Code with --dangerously-skip-permissions
5. Send gt prime to load context
6. Send startup prompt

Similar pattern to refinery startup in internal/refinery/manager.go


Move disk 2: B → A

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


Digest: mol-deacon-patrol

Patrol 20: All healthy - handoff cycle


Merge: toast-1767146237529

branch: polecat/toast-1767146237529
target: main
source_issue: toast-1767146237529
rig: gastown


Digest: mol-deacon-patrol

Patrol complete: inbox empty, all agents healthy (mayor, 2 witnesses, 2 refineries), no orphans


OSS Launch Readiness

Track all issues blocking or affecting OSS launch quality.

P0 Blocker:
- gt-ofl2: ProcessMRFromQueue not implemented

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

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

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


Digest: mol-deacon-patrol

Patrol 8: all clear


Digest: mol-deacon-patrol

Patrol cycle 3: All agents healthy


Move disk 1: B → C

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


Move disk 1: A → B

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


Cross-project dependency workflow (Gas Town side)

Gas Town integration for cross-project dependencies.

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

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

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

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


Fix SQL injection in convoy panel getTrackedIssueStatus

convoy.go:151-152 interpolates convoyID directly into SQL query without sanitization. Add input validation for hq-* pattern.


Digest: mol-deacon-patrol

Patrol cycle 51: All healthy


Digest: mol-deacon-patrol

Patrol 14: Routine


Digest: mol-deacon-patrol

Patrol 19: all clear


Digest: mol-deacon-patrol

Patrol 2: all clear, 9 sessions healthy


MEOW Stack Evolution: Higher-Order Workflow Abstractions

Molecular Expression of Work (MEOW) - the full taxonomy of workflow abstractions.

## Current Hierarchy

```
WORK TRACKING              WORKFLOW EXECUTION
─────────────              ──────────────────

Bead (issue)               Step (action)
    │                          │
    ▼                          ▼
Epic (bead group)          Molecule (runtime)
    │                          │
    ▼                          │
    └───────► CAMPAIGN ◄───────┘
                  │
                  ▼
             Schematic (domain template)
                  │
                  ▼
             Protocol (interface/type)
                  │
                  ▼
             Catalyst (meta-generator)
                  │
                  ▼
             Mol Mall (distribution)
```

## Key Concepts

1. **Campaign** (gt-camx5): Molecule-wrapped Epic graph for orchestrated execution
2. **Schematic** (gt-8ws7o): Domain-level formula composition
3. **Protocol** (gt-y3jb9): Type system for formulas
4. **SDK** (gt-ihzqr): Developer tooling (Forge, Lab, Validator)
5. **Mol Mall** (gt-vm85o): Package registry for distribution

## Design Principles

- Chemistry metaphor: atoms → molecules → compounds → materials
- Two orthogonal dimensions: work tracking × workflow execution
- Campaign is the convergence point
- Everything compiles down to executable molecules

## Origin

Discussion: 2024-12-26, Mayor session
Related: docs/formula_evolution.md
Foundation: gt-8tmz (Molecule Algebra)


Merge: rictus-1767073382273

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


Digest: mol-deacon-patrol

Patrol cycle 31: All healthy, no incidents


gt spawn --create should auto-add polecat if missing

## Problem

`gt spawn gastown --issue gt-xxx --create` fails if no polecats exist.

## Current Behavior

```
Error: auto-select polecat: no available polecats in rig 'gastown'
```

## Expected Behavior

`--create` should:
1. Create a new polecat if none exist
2. Or create the specified polecat if `gt spawn gastown/NewName --create`

## Workaround

Must manually run `gt polecat add gastown Name` first.

## Principle

Agent UX should be forgiving - if I say spawn with --create, make it work.


Move disk 1: A → B

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


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

Patrol 20: final patrol before handoff


Move disk 2: C → B

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


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

Patrol 18: All healthy


gt doctor: add Claude settings.json validation

Add a new doctor check to validate Claude Code settings in worker directories:

**Check for:**
1. .claude/settings.json exists in polecats/*, crew/*, witness/rig, refinery/rig
2. SessionStart hook has 'gt prime' command
3. Autonomous roles (polecat, witness, refinery) have 'gt mail check --inject' in SessionStart
4. Interactive roles (crew, mayor) have mail check in UserPromptSubmit only

**Auto-fix capability:**
Use internal/claude.EnsureSettingsForRole() to create missing settings files.

Context: The spawn priming race condition fix (gt-6957) added embedded settings templates. Doctor should validate these are in place.


Digest: mol-deacon-patrol

Cycle 14: quiet


Digest: mol-deacon-patrol

Patrol 13: nominal


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


Digest: mol-deacon-patrol

Patrol complete: all agents healthy, cycling at 20 patrols


Review PR #44: docs: Fix Quick Start to use gt mayor attach

Review and approve/request changes for PR #44. Check docs accuracy. If good, approve with gh pr review --approve.


Digest: mol-deacon-patrol

Patrol 13: Routine


Witness Patrol

Per-rig worker monitor patrol loop with progressive nudging.


Digest: mol-deacon-patrol

Patrol #11


Evaluate pending async gates

Evaluate pending async gates.

Gates are async coordination primitives that block until conditions are met.
The Deacon is responsible for monitoring gates and closing them when ready.

**Timer gates** (await_type: timer):
Check if elapsed time since creation exceeds the timeout duration.

```bash
# List all open gates
bd gate list --json

# For each timer gate, check if elapsed:
# - CreatedAt + Timeout < Now → gate is ready to close
# - Close with: bd gate close <id> --reason "Timer elapsed"
```

**GitHub gates** (await_type: gh:run, gh:pr) - handled in separate step.

**Human/Mail gates** - require external input, skip here.

After closing a gate, the Waiters field contains mail addresses to notify.
Send a brief notification to each waiter that the gate has cleared.


Digest: mol-deacon-patrol

P7: stable


Swarm completion detection and auto-close

Detect when all epic children are closed and auto-close the swarm molecule.

Core logic:
1. After any issue closes, check if it was part of a swarm
2. Query bd list --parent=<epic> --status=open
3. If empty (all closed), close the swarm molecule
4. Fire completion event for activity feed

Can be implemented as:
- Part of Witness patrol
- Or as a bd hook triggered on issue close
- Or as a gt swarm check command called periodically

Reference: ~/gt/docs/swarm-architecture.md - Recovery Protocol

Dependencies: gt-kc7yj.1 (gt swarm refactor)


gt convoy list --tree: Show convoy + child status tree

Add a --tree flag to 'gt convoy list' that shows convoys with their child issues in a tree format.

Example output:
```
🚚 hq-cv-wvqi6: Boot + Polish swarm (16/17)
├── ✓ bd-11lm: Increase ClaudeStartTimeout
├── ✓ bd-49oe: Cache GetGitDir()
├── ○ gt-74ivo: Witness: Don't nuke polecats with open MRs  ← remaining
└── ...

🚚 hq-cv-w3nm6: Messaging Channels (4/10)
├── ✓ gt-0q3cg: Add isQueueAddress()
├── ○ gt-27bzi: Add gt mail announces
└── ...
```

Makes convoy progress visible at a glance without running 'gt convoy status' on each one.

(Moved from hq-q3tki)


Digest: mol-deacon-patrol

Patrol 18: All healthy


Digest: mol-deacon-patrol

Patrol 202: All agents healthy, 10 polecats working, 3 refineries processing. No incidents.


Track merge requests as beads (type=merge-request)

Currently MRs are tracked in .gastown/refinery.json. For HOP audit trail and entity CV tracking, merge requests should be Beads entries with type=merge-request. This enables:
- Full audit trail of what was merged, when, by whom
- Entity chain contributions (who validated what)
- Cross-rig visibility of merge activity

The refinery would create an MR bead when work enters the queue, update status as it progresses (open → in_progress → merged/rejected).

Part of Beads-as-data-plane vision from HOP.


Digest: mol-deacon-patrol

Patrol 20: Final cycle, all services healthy, handoff


Digest: mol-deacon-patrol

P6: stable, beads polecats exited


Digest: mol-deacon-patrol

Patrol 9: All green


Digest: mol-deacon-patrol

Patrol 17: All healthy


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 12: routine


Daemon sending heartbeat to Mayor - should not

Daemon appears to be sending heartbeat messages to Mayor, but Mayor should not receive heartbeats. Observed at least once or twice - needs investigation to confirm and fix.


Create rig settings/ directory for rig configuration

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


MQ metrics: pending count, processing time, success rate

Implement merge queue metrics collection.

Metrics to track:
- mq_pending_count: MRs waiting
- mq_processing_time: Time from submit to merge (histogram)
- mq_success_rate: Merges vs rejections
- mq_conflict_rate: How often conflicts occur
- mq_test_failure_rate: Test failures

Storage options:
- Simple: JSON file with rolling stats
- Advanced: Prometheus-compatible metrics endpoint

Display via:
- gt mq stats: summary statistics
- Dashboard widget (separate task)

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


Digest: mol-deacon-patrol

Patrol cycle 14: All agents healthy


Digest: mol-deacon-patrol

Patrol 6: routine


gt-gastown-polecat-dementus

gt-gastown-polecat-dementus

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


Merge: nux-mjxaphp6

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


Digest: mol-deacon-patrol

Patrol 19: all healthy


Test Patrol Parent

Test parent for Christmas Ornament pattern


Digest: mol-deacon-patrol

Patrol complete: checked inbox (0 msgs), health check passed (all rigs healthy), cleaned 3 stale locks


Merge: rictus-mjvtzdm2

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol cycle 11: all healthy


Digest: mol-deacon-patrol

Patrol #8: nominal


Merge: cheedo-1767088553821

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


Daemon sends heartbeat to Mayor instead of Deacon


Implement gt sling command

The unified work dispatch command.

```bash
gt sling <thing> <target> [options]
```

Implements spawn + assign + pin in one operation. See sling-design.md.

Acceptance:
- [ ] Parse thing (proto name, issue ID, epic ID)
- [ ] Parse target (agent address)
- [ ] Spawn molecule if proto
- [ ] Assign to target agent
- [ ] Pin to agent's hook (pinned bead)
- [ ] Support --wisp flag for ephemeral
- [ ] Support --molecule flag for issue+workflow
- [ ] Error if hook already occupied (unless --force)


Digest: mol-deacon-patrol

Patrol 7: All healthy


Digest: mol-deacon-patrol

Patrol 3: all clear


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Cycle 189: Nominal


Merge: bix-mjufugoo

branch: polecat/bix-mjufugoo
target: main
source_issue: bix-mjufugoo
rig: gastown


Digest: mol-deacon-patrol

Patrol 204: Fast pass, all nominal


Witness: aggregate completion and notify Mayor

## Problem
No signal when swarm completes. Mayor must manually check.

## ZFC-Compliant Solution
Add step to `mol-witness-patrol.formula.toml`:

```toml
[[step]]
id = "check-swarm-completion"
title = "Report swarm completion to Mayor"
description = """
1. Check state.json for active swarm tracking:
   - swarm_id, start_time, assigned_beads[], completed_beads[]
2. For each completed merge (from cleanup step):
   - Add bead to completed_beads
3. If all assigned_beads are in completed_beads:
   - Calculate duration
   - Send summary to Mayor:
     gt mail send mayor/ -s "SWARM_COMPLETE: <swarm_id>" -m "All N polecats merged in Xm"
   - Clear swarm tracking from state.json
"""
depends_on = ["cleanup-merged-polecats"]
```

## Swarm Initialization
When Mayor slings a batch, they should:
```bash
# Mayor creates swarm tracking
gt mail send <rig>/witness -s "SWARM_START" -m '{"swarm_id": "batch-123", "beads": ["bd-a", "bd-b", "bd-c"]}'
```

Witness parses SWARM_START and initializes tracking in state.json.

## Why This Works
- Mayor initiates batch with SWARM_START mail
- Witness tracks progress in its own state
- Witness signals completion via mail
- All coordination is agent-to-agent via mail

## Files
- formulas/mol-witness-patrol.formula.toml


Digest: mol-deacon-patrol

Patrol 3: OK


Move disk 3: C → A

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


Move disk 1: B → C

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


Merge: dementus-mjw062kt

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


Add 'gt rig start <rig>' to start witness and refinery together

After a town restart, need a convenient way to start both witness and refinery for a rig.

Current workflow requires two commands:
  gt witness start <rig>
  gt refinery start <rig>

Desired:
  gt rig start <rig>  # starts both witness and refinery

Should also support:
  gt rig stop <rig>   # stops both
  gt rig restart <rig> # restarts both


Deacon marching orders: pinned bead with rounds molecule

Create a pinned bead that defines the Deacon's rounds molecule - its "kernel".

## Concept

Like `gt prime` gives agents their context, a pinned bead gives the Deacon
its operating instructions. This bead defines:

1. The rounds molecule (steps to execute each wake)
2. Registered plugins (scheduled, event-triggered)
3. Configuration (timeouts, thresholds, escalation rules)

## Pinned Bead Structure

```yaml
# gt-deacon-kernel (pinned)
title: "Deacon Kernel Configuration"
type: policy
pinned: true

molecule: mol-deacon-rounds
  steps:
    - session-check: "Check context budget, cycle if needed"
    - health-scan: "Check Mayor, Witnesses, Refineries, Crew"
    - lifecycle: "Process pending lifecycle requests"
    - plugins: "Run due scheduled plugins"
    - events: "Process timer callbacks, event subscriptions"
    - complete: "Update heartbeat, return to wait"

plugins:
  scheduled:
    - name: beads-hygiene
      schedule: "0 2 * * *"  # 2 AM daily
    - name: branch-cleanup
      schedule: "0 4 * * 0"  # 4 AM Sundays

  event_triggers:
    - event: "issue.created"
      plugin: work-oracle
    - event: "mr.submitted"
      plugin: review-oracle

config:
  session_cycle_threshold_turns: 50
  session_cycle_threshold_hours: 4
  health_scan_timeout_seconds: 60
  plugin_timeout_minutes: 30
  escalation_after_failures: 3
```

## Reading Marching Orders

On wake, Deacon:
1. `bd show --pinned` to find the kernel bead
2. Parse molecule steps
3. Execute in order

## Updating the Kernel

To change Deacon behavior:
1. `bd update gt-deacon-kernel` with new config
2. Next wake cycle picks up changes
3. No code changes required

## Bootstrap

If no pinned bead exists, Deacon uses hardcoded defaults from DEACON.md.
First installation creates the pinned bead.


Digest: mol-deacon-patrol

Patrol 6


mol-deacon-patrol

Deacon patrol molecule template. Label: template


Zombie session detection for refinery/witness

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

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

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

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


Digest: mol-deacon-patrol

Patrol cycle 71: All healthy


Digest: mol-deacon-patrol

Patrol 121: All agents healthy, no incidents


Merge: gt-i4kq

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


gt mail: Cross-level routing is broken

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

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

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

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

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

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


Move disk 2: A → C

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


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

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

## Variables

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

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

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

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

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

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

Calculate: minutes since last activity.
Needs: capture

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

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

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

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

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

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

Record decision and rationale.
Needs: load-history

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

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

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

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

**none**: No action needed.

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

## Output

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

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


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 10: all healthy


Integration test: simple file creation

Test task for polecat integration test (gt-7psb8).

Simple task: Create a file ~/gt/gastown/test-polecat-integration.txt with content 'Polecat integration test successful'.

This is an intentionally trivial task to verify the polecat → witness → refinery → merged flow works end-to-end.


refinery Handoff

# Merge queue tracking
last_processed_branch: null
branches_merged_this_cycle: 0


Delete hook types from internal/wisp

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

The entire file may become empty or minimal.


Digest: mol-deacon-patrol

Patrol cycle 11: all healthy


Fix N+1 query problem in convoy status fetching

getTrackedIssueStatus spawns a new bd show for each tracked issue. With 10 convoys x 5 issues = 50+ subprocesses every 10s. Consider batching or caching.


Add unit tests for internal/mail router and mailbox

attached_args: Add unit tests for mail router and mailbox

Add tests for mail routing and mailbox functionality.

## Files to create
- internal/mail/router_test.go
- internal/mail/mailbox_test.go

## Test cases for router
1. Route() resolves addresses correctly
2. Route() handles rig/role format
3. Route() handles rig/crew/name format
4. Invalid addresses return error

## Test cases for mailbox
1. Send() writes message to mailbox
2. Inbox() lists messages
3. Read() retrieves message by ID
4. Delete() removes message
5. Messages persist correctly

## Acceptance criteria
- [ ] router_test.go with 4+ tests
- [ ] mailbox_test.go with 5+ tests
- [ ] Tests pass: go test ./internal/mail/...
- [ ] Coverage > 60%


Digest: mol-deacon-patrol

Patrol cycle 6: All healthy


gt convoy create: Make --notify a boolean flag with default

--notify requires an argument but the default (mayor/) is sensible. Should work as boolean flag that defaults to mayor/ when no arg given.


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 6: All agents healthy


Implement/document gt sling mechanism

Investigate and implement the gt sling command for attaching molecules to crew workers. Check if gt sling exists, design the flow (mail-based vs direct pin vs wisp spawn), implement in gastown CLI, integrate with bd mol/wisp/pin commands.


Digest: mol-deacon-patrol

Cycle 16


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol cycle 5: routine, healthy


Digest: mol-deacon-patrol

Patrol 15: Green


Digest: mol-deacon-patrol

Patrol #9: Stable


Move disk 3: B → C

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


BranchPushedToRemote: Fetch remote tracking ref if not present locally

BranchPushedToRemote uses RemoteBranchExists (git ls-remote) to check if remote branch exists, but then compares with local origin/branch ref which may not exist if we just pushed.

## Repro
1. Push a new branch: git push -u origin branch-name
2. The local tracking ref origin/branch-name may not exist yet
3. BranchPushedToRemote errors: 'unknown revision origin/branch..HEAD'

## Fix
In BranchPushedToRemote, after confirming remote branch exists, run git fetch to ensure we have the local ref before comparing.

## Discovered
While implementing gt-bca67 (require pushed branch before MR creation)


Digest: mol-deacon-patrol

Patrol cycle 17


Use Beads issue status as spawn source of truth

Currently witness tracks spawned issues in .gastown/witness.json to prevent re-spawning:

{"spawned_issues": ["gt-abc1", "gt-def2", ...]}

This is redundant with Beads issue status (in_progress). The witness could query:
  bd list --status=in_progress

The local list serves as a performance cache to avoid querying beads every cycle. Consider:
1. Use Beads as source of truth
2. Keep local cache with TTL
3. Sync cache on witness start

This simplifies state management and ensures consistency.


Design: Deacon exponential backoff when town is idle

## Problem

When the user goes to sleep and all workers have stopped, the Deacon continues
polling at full speed (every daemon heartbeat). This wastes resources and creates
unnecessary log noise.

## Requirements

1. **Gradual slowdown**: Deacon patrol frequency should exponentially back off
   when there's no activity in the town.

2. **Wake on activity**: Any gt or bd command (human or agent) should reset
   the backoff immediately.

3. **Daemon coordination**: Deacon needs to "program" the daemon for next
   heartbeat duration.

## Design Considerations

### Option A: Daemon tracks last-activity timestamp
- Daemon mechanically slows heartbeat based on time since last activity
- Activity signal comes from gt/bd command hooks
- Simple, no Deacon state needed
- But: Daemon is "dumb" by design - adding intelligence here feels wrong

### Option B: Deacon tracks patrol-count-since-activity
- Deacon maintains counter (via label on patrol molecule or state.json)
- Each idle patrol increments counter, calculates next sleep
- Deacon tells daemon "wake me in X minutes"
- More complex but keeps intelligence in AI agent

### Option C: Discovery-based (preferred if feasible)
- Can we detect "no activity" without explicit counters?
- Ideas:
  - Compare current time to last git commit across all clones?
  - Check tmux activity timestamps?
  - Look at beads modification times?
- Pros: No state to manage
- Cons: May be expensive to compute, could miss activity

### Wake mechanism
- Hook on gt commands (gt.hooks.pre-command or similar)
- Hook on bd commands (bd.hooks.pre-command)
- Both should signal daemon (SIGUSR2?) or write to activity file
- Daemon reads activity file on each heartbeat, resets backoff if fresh

### Backoff schedule (strawman)
| Idle patrols | Next heartbeat |
|--------------|----------------|
| 0-5          | 5 min (default) |
| 6-10         | 10 min |
| 11-20        | 30 min |
| 21+          | 60 min (max) |

## Open Questions

1. Should tmux activity count as "activity"? (cursor movement, typing)
2. How does Deacon communicate next-heartbeat to daemon?
3. Where to store backoff state? (daemon state.json? deacon state.json? label?)
4. Should wake be instant (SIGUSR) or next-heartbeat?

## Implementation Sketch

Activity file written by hooks at ~/gt/daemon/activity.json:
- last_command: timestamp
- command: the gt/bd command that ran
- actor: who ran it


Digest: mol-deacon-patrol

Patrol 9


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 11: OK


Merge: ace-mjwjb633

branch: polecat/ace-mjwjb633
target: main
source_issue: ace-mjwjb633
rig: gastown
agent_bead: gt-gastown-polecat-ace


Digest: mol-deacon-patrol

Patrol 11: All healthy.


Create patrol formula YAML files

Create formula YAML files for:
- mol-deacon-patrol.formula.yaml
- mol-witness-patrol.formula.yaml
- mol-refinery-patrol.formula.yaml

Use the step definitions currently in molecules_patrol.go as reference.
Store in .beads/formulas/


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol complete: Force-killed and restarted 3 unresponsive agents (wyvern/witness, gastown/witness, gastown/refinery). Restarted mayor and beads agents. All 17 sessions now healthy.


Review PR #53: fix: Add retry logic for Enter key send in NudgeSession/NudgePane

Review PR #53. Check retry logic is sound. Test locally if needed. Approve with gh pr review --approve if good.


Analysis: Beads database size and hygiene strategy

Audit beads database size and plan medium-term hygiene.

## Questions
1. How many issues total (including tombstones)?
2. Size of issues.jsonl?
3. Growth rate per day/week?
4. What percentage are tombstones?

## Hygiene Topics
- Compaction: squash tombstones periodically
- Archival: move old closed issues to archive file
- Pruning: delete truly stale items (test beads, old MRs)
- Sync efficiency: large JSONL = slow sync

## Action Items
- [ ] Count total issues by status
- [ ] Count tombstones
- [ ] Measure file sizes
- [ ] Propose hygiene schedule


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 #2: All healthy, no changes


Digest: mol-deacon-patrol

Patrol 17: all clear


Digest: mol-deacon-patrol

Patrol 2: All agents healthy, routine check


Inconsistent error wrapping patterns

Error handling is inconsistent across the codebase:

1. Some functions use fmt.Errorf with %w for wrapping, others don't
2. return nil, nil patterns (40+ occurrences) sometimes represent 'not found' and sometimes 'error but continue' - should use sentinel errors
3. Some places return nil for errors when they should propagate them

Examples of nil,nil that might need review:
- internal/git/git.go:272, 308
- internal/crew/manager.go:227
- internal/witness/manager.go:517, 523, 530, 775
- internal/beads/beads.go:225, 492


Deacon patrol: Janitorial cleanup patterns

Patterns discovered during town cleanup that could be automated in Deacon's patrol step:

## Stale Issue Detection

1. **Stale in_progress issues** - Issues marked in_progress for >N days without activity
   - Example: 9 issues in_progress, some likely complete
   - Action: Report list, optionally nudge assignee

2. **Duplicate issues** - Same title with different IDs
   - Example: gt-87jz and gt-qp2w both 'mol-witness-patrol'
   - Action: Flag for human review

3. **Orphaned issues** - Referenced in commits but still open
   - bd doctor already detects: 'hq-65jk (commit f9e9034d)'
   - Action: Report, suggest closing

4. **Stale test messages** - Messages with 'test' in title older than N days
   - Example: gt-54kn, gt-1ero, gt-nriy, gt-wrw2, gt-pnu4, gt-g1ud, gt-b5sh
   - Action: Auto-close or flag

## File System Cleanup

5. **Log file accumulation** - daemon.log and rotated .log.gz files
   - Found 8+ log files across rigs
   - Action: Rotate, compress, delete old (>7 days)

6. **Beads directory size** - Town .beads/ is 65MB
   - Action: Monitor growth, alert on threshold

## Database Health

7. **Legacy database fingerprints** - Older DBs without fingerprint
   - bd doctor warns about this
   - Action: Report, suggest migration

## Cross-Reference Integrity

8. **Gastown↔Beads issue sync** - Issues filed in wrong project
   - Example: gt-8tmz.* describes Beads work but no bd-* issues
   - Action: Detect cross-references, verify both sides exist

## Implementation Notes

These could be added to mol-deacon-patrol.formula.yaml as cleanup substeps:
- Daily: Log rotation, stale issue report
- Weekly: Duplicate detection, orphan check
- Monthly: Size monitoring, archive old closed issues


Day 2.4: Add timeout fallback for dead agents

For truly dead agents that can't report their own death:
- Daemon tracks last_seen timestamp from heartbeats
- If no heartbeat for N minutes AND state=running, mark state=dead
- This is fallback only, not primary state source

Parent: gt-d0jqp


Digest: mol-deacon-patrol

Patrol 19: clear


Move disk 1: B → C

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


Move disk 2: A → C

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


Polecat beads not synced with rig beads

When gt spawn assigns an issue to a polecat, the polecat cannot find the issue because:

1. Rig beads at /gt/gastown/.beads contains gt-th7
2. Polecat beads at /gt/gastown/polecats/dementus/.beads does NOT have gt-th7
3. bd sync in polecat dir pulls from beads-sync branch which doesn't have the new issue
4. Rig bd sync uses 'main' branch, causing a branch mismatch

The polecat gets a work assignment for an issue it literally cannot see.

## Root Cause

- Rig beads and polecat beads are separate git-tracked copies
- No mechanism to propagate newly created issues from rig to polecats before assignment
- Sync branch configuration mismatch between rig and polecats

## Fix Options

1. gt spawn should sync rig beads before assigning work
2. gt spawn should sync polecat beads after assignment
3. Use shared beads (symlink or same DB) instead of copies
4. Push new issues immediately on create

Note: This sync mismatch is resolved by gt-9nf (fresh polecats). Rather than fixing sync between stale clones, we'll always create fresh worktrees. This issue documents the root cause for posterity.


Witness emits activity events

Witness emits events to activity stream for patrol activity:

Events to emit:
- patrol_started: When witness begins patrol cycle
- polecat_checked: When witness checks a polecat
- polecat_nudged: When witness nudges a stuck polecat
- escalation_sent: When witness escalates to Mayor/Deacon
- patrol_complete: When patrol cycle finishes

This replaces stats tracking in .runtime/witness.json


Digest: mol-deacon-patrol

Patrol #6: All nominal


Digest: mol-deacon-patrol

Patrol complete: No callbacks, no gates, witness/refinery healthy, no orphans, clean cycle


Move disk 2: C → B

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


load-context

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

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


Digest: mol-deacon-patrol

Patrol cycle 66: All healthy


Digest: mol-deacon-patrol

Patrol cycle 5: All healthy


gt convoy create: Fix notify slot warning

When creating convoy with --notify, get warning:
```
⚠ Warning: couldn't set notify slot: exit status 1
```

But notification target still shows in status. Investigate slot setter.


End-of-cycle inbox hygiene

Verify inbox hygiene before ending patrol cycle.

**Step 1: Check inbox state**
```bash
gt mail inbox
```

Inbox should be EMPTY or contain only just-arrived unprocessed messages.

**Step 2: Archive any remaining processed messages**

All message types should have been archived during inbox-check processing:
- WITNESS_PING → archived after acknowledging
- HELP/Escalation → archived after handling
- LIFECYCLE → archived after processing

If any were missed:
```bash
# For each stale message found:
gt mail archive <message-id>
```

**Goal**: Inbox should have ≤2 active messages at end of cycle.
Deacon mail should flow through quickly - no accumulation.


Add merge-request type to Beads schema

Define the merge-request bead type with fields:
- branch: source branch (e.g., polecat/Nux/gt-xxx)
- target_branch: destination (main or integration/xxx)
- source_issue: the work being merged (gt-xxx)
- worker: who did the work
- rig: which rig
- merge_commit: (filled on close) SHA of merge commit
- close_reason: (filled on close) success/failure details

This may require beads schema changes or just convention.


Digest: mol-deacon-patrol

Patrol cycle 19: All healthy


mol-deacon-patrol


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol 20: All healthy. Handoff after 20 cycles.


Move disk 1: C → A

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


Move disk 2: C → B

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


Digest: mol-deacon-patrol

Patrol 17: all healthy


Verify initial state

All 10 disks stacked on peg A. Largest on bottom.


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.


Digest: mol-deacon-patrol

Cycle 6: healthy


Merge: nux-mjxeh79t

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


Shell command injection in engineer.go:349

Test commands executed via sh -c without escaping: exec.CommandContext(ctx, "sh", "-c", e.config.TestCommand). Malicious mergequeue.yaml could execute arbitrary commands. Fix: Validate/escape test command configuration or use exec.Command with proper argument splitting.


gt-gastown-polecat-slit

gt-gastown-polecat-slit

role_type: polecat
rig: gastown
agent_state: running
hook_bead: gt-bho9
role_bead: gt-polecat-role
cleanup_status: clean
active_mr: gt-1kuox
notification_level: null


Add accounts.yaml config parsing to gt

Parse ~/gt/mayor/accounts.yaml with structure: accounts map (handle -> email, config_dir) and default field. This is the foundational config that other account features depend on. Location follows existing town-level config pattern in mayor/.


Implement gt mol attach-from-mail command

Allow agents to self-pin work from mail.

Usage: gt mol attach-from-mail <mail-id>

Behavior:
1. Read mail body for attached_molecule field
2. Attach molecule to agent's hook
3. Mark mail as read
4. Return control for execution

Handles case where work was sent via mail but not slung to hook.


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 27: all polecats working, jack session started


Digest: mol-deacon-patrol

Patrol 130: All healthy


Digest: mol-deacon-patrol

Patrol 1: cleaned 3 stale locks, 3 orphan processes, doctor passed


Merge: gt-j6s8

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


Move disk 2: B → A

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


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 19: Mayor OK, 11 sessions


Digest: mol-deacon-patrol

Patrol 18: 3 rigs healthy


Remove schedule/phase terminology from code

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

## Found Issues

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

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

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

## Why This Matters

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

## What To Keep

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


list: static mailing list lookup

Static mailing list support via config file.

## Deliverables

1. Load lists from ~/gt/config/lists.json
2. Parse list:name syntax in router
3. Fan-out at send time (same as @group)
4. Error handling for unknown list names

## Example
```bash
gt mail send list:oncall -s "Alert" -m "System down"
# Expands to: mayor/, gastown/witness, beads/witness
# Creates 3 message copies
```

## Dependencies
- Config directory (gt-i6jvc)

## Acceptance
- list:oncall resolves to configured members
- Each member gets own message copy
- Unknown list returns clear error


Check own context limit

Check own context limit.

The Deacon runs in a Claude session with finite context. Check if approaching the limit:

```bash
gt context --usage
```

If context is high (>80%), prepare for handoff:
- Summarize current state
- Note any pending work
- Write handoff to molecule state

This enables the Deacon to burn and respawn cleanly.


Witness patrol: cleanup idle orphan polecats

Add patrol step to find and cleanup polecats that are idle with no assigned issue. These orphans occur when polecats crash before sending DONE or Witness misses the message. Patrol should verify git is clean before removing worktree. Part of gt-rana.


Digest: mol-deacon-patrol

Patrol 10: Mayor OK, 11 sessions


Swarm: ephemeral rig support

PGT has ephemeral rigs for swarms - temporary worker groups that are destroyed after landing.

Missing Features:
- gt swarm init [--rig <name>|--git-url <url>] [--num-workers N]
- gt swarm worker add/remove/list <rig-id>
- gt swarm rigs - List ephemeral rigs
- gt swarm destroy <rig-id> - Destroy ephemeral rig

Directory structure:
<workspace>/mayor/workers/<rig-id>/
├── rig.json (metadata)
├── alice/ (git clone)
├── bob/
└── carol/

PGT Reference: gastown-py/src/gastown/ephemeral.py

Note: Beads issue gt-kmn.12 mentions this but implementation is missing.


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol cycle 9


Merge: furiosa-mjxap5fz

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


Digest: mol-deacon-patrol

Patrol OK: no mail, 8 polecats working, all witnesses/refineries up


Digest: mol-deacon-patrol

Patrol 17: All healthy


Nudge newly spawned polecats

Nudge newly spawned polecats that are ready for input.

When polecats are spawned, their Claude session takes 10-20 seconds to initialize. The spawn command returns immediately without waiting. This step finds spawned polecats that are now ready and sends them a trigger to start working.

**ZFC-Compliant Observation** (AI observes AI):

```bash
# View pending spawns with captured terminal output
gt deacon pending
```

For each pending session, analyze the captured output:
- Look for Claude's prompt indicator "> " at the start of a line
- If prompt is visible, Claude is ready for input
- Make the judgment call yourself - you're the AI observer

For each ready polecat:
```bash
# 1. Trigger the polecat
gt nudge <session> "Begin."

# 2. Clear from pending list
gt deacon pending <session>
```

This triggers the UserPromptSubmit hook, which injects mail so the polecat sees its assignment.

**Bootstrap mode** (daemon-only, no AI available):
The daemon uses `gt deacon trigger-pending` with regex detection. This ZFC violation is acceptable during cold startup when no AI agent is running yet.


Digest: mol-deacon-patrol

Final patrol cycle 20: all systems healthy


Merge: gt-2hwi9

branch: polecat/furiosa-mjw349y2
target: main
source_issue: gt-2hwi9
rig: gastown
agent_bead: gt-gastown-polecat-furiosa


Digest: mol-deacon-patrol

Cycle 7


Update role prompts with hook protocol

Update role prompt templates to include hook-first protocol.

Templates to update:
- polecat.md.tmpl
- deacon.md.tmpl
- witness.md.tmpl
- refinery.md.tmpl
- crew.md.tmpl

Each should include:
1. Check hook first (gt mol status)
2. If empty, check mail for attached work
3. Self-pin protocol if needed


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

Patrol cycle 10: All healthy.


Digest: mol-deacon-patrol

Patrol cycle 10: All quiet.


Test Epic: GGT MVP Validation


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

Patrol 4: quiet


Digest: mol-deacon-patrol

Patrol 2: inbox empty, all agents healthy, fixed 1 orphan process


Support nested expansion formulas


Digest: mol-deacon-patrol

Patrol cycle 15: nominal


Move disk 2: C → B

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


Town-level beads: Real DB for coordination mail

Implement Option A from mail redesign: Town gets real beads DB for coordination.

## Background

Mail is now Beads. But currently:
- Town .beads/redirect points to rig beads
- mayor/mail/ has legacy JSONL files
- Cross-rig coordination has no clear home

## Design

Town beads = coordination, cross-rig mail, mayor inbox, handoffs
Rig beads = project issues, work items

Matches HOP hierarchy: platform > project > worker

## Structure

~/gt/
  .beads/           # REAL beads DB (prefix: gm-)
  mayor/
    town.json
    state.json      # NO mail/ directory
  gastown/
    .beads/         # Rig beads (prefix: ga-)

## Tasks

1. Delete ~/gt/.beads/redirect
2. Run bd init --prefix gm at ~/gt/ (town beads)
3. Delete ~/gt/mayor/mail/ directory
4. Update gt mail to use beads not JSONL
5. Add mail fields (thread_id, reply_to, msg_type)
6. Update gt prime for two-tier model
7. Update docs/architecture.md

## Addressing

- mayor/ -> town beads
- rig/agent -> rig beads
- Cross-rig -> town beads


Digest: mol-deacon-patrol

Patrol 13: All clear


Digest: mol-deacon-patrol

Patrol 7: all clear


Document crew worker patrol integration

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


Move disk 1: C → A

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


Merge: gt-cp2s

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


mol-deacon-patrol


Session cycling: Auto-spawn successor when context full

Enable automatic session succession for crew workers.

When a crew worker's context fills up (>80%), they should:
1. Write handoff mail to themselves
2. Signal session end
3. System auto-spawns successor session
4. Successor reads handoff, finds attached work, auto-continues

This completes the autonomous overnight work pattern from gt-9g82.

Depends on:
- Detecting context fullness (Claude Code API?)
- Session spawning mechanism (tmux/daemon)
- Handoff protocol already implemented


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol cycle 5: all healthy


Digest: mol-deacon-patrol

Patrol 5: All healthy


Digest: mol-deacon-patrol

Patrol #4: All systems nominal


Digest: mol-deacon-patrol

Patrol cycle 2: All agents healthy, 6 health pings sent


Daemon should auto-start as part of town bootstrap

The Go daemon should be started automatically when the town boots up (mol-gastown-boot). Currently it requires manual 'gt daemon start'.

The daemon is critical infrastructure - it monitors the Deacon and nudges it when naked. Without it, the Deacon patrol loop doesn't run.


Digest: mol-deacon-patrol

Patrol 11: All healthy


Execute registered plugins

Execute registered plugins.

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

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

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

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

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

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


Delete .runtime/*.json observable state

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

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

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

This is the cleanup step after observability is working.


Digest: mol-deacon-patrol

Patrol 4: OK


Move disk 1: C → A

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


Add stale-attachments doctor check

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

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


Digest: mol-deacon-patrol

Patrol 7: Nominal


Move disk 3: B → C

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


Digest: mol-deacon-patrol

Patrol 11: all healthy


Review PR #42: fix(done): detect default branch instead of hardcoding 'main'

Review PR #42. Verify default branch detection works correctly. Approve with gh pr review --approve if good.


Digest: mol-deacon-patrol

Cycle 7: quiet


Fix role detection for nested rig structures

When gastown/ has its own mayor/ dir, workspace detection finds it as town root instead of ~/ai. This breaks polecat/refinery/witness detection when running from within a rig.


Merge: gt-3x1.3

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Idle Town Principle

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

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

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

## Second-Order Monitoring

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

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


Move disk 2: B → A

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


Move disk 1: C → A

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


Move disk 3: C → A

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


Digest: mol-deacon-patrol

Cycle 300: All healthy, refinery queue 7


Move disk 1: C → A

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


Move disk 1: A → B

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Move disk 3: A → B

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


Digest: mol-deacon-patrol

Patrol cycle 14: routine


Move disk 3: A → B

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


implement

Implement the solution for gt-test. 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


Digest: mol-deacon-patrol

Patrol cycle 2: All 6 agents healthy, no incidents


Digest: mol-deacon-patrol

Patrol 13 complete


gt-gastown-polecat-furiosa

gt-gastown-polecat-furiosa

role_type: polecat
rig: gastown
agent_state: running
hook_bead: gt-csbjj
role_bead: gt-polecat-role
cleanup_status: has_stash
active_mr: gt-lcuxo


Move disk 1: B → C

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


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

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


Documentation humility pass

Update documentation with humble framing.

## Changes Needed

### README.md

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

### Architecture docs

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

### CLAUDE.md files

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

## Tone

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

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

## Files to Review

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


gt sling command implementation

Implement the gt sling command for handoff with attached work.

## Command Signature

```bash
gt sling <bead-id> [-s subject] [-m message]
```

## Behavior

1. Validate the bead exists: bd show <bead-id>
2. Create wisp on agents hook:
   - File: .beads-wisp/hook-<agent>.wisp.yaml
   - Content: bead_id, slung_at, optional context
3. Optionally send handoff mail with subject/message
4. Exit cleanly (or signal restart)

## Wisp Format

```yaml
type: slung-work
bead_id: gt-xxx
slung_at: 2025-12-24T...
slung_by: crew/joe
context: "Optional message"
```

## Files to Create/Modify

- cmd/gt/sling.go (new)
- internal/wisp/wisp.go (may need creation)
- internal/wisp/hook.go (hook reading)

## Notes

- Keep it simple - this is connector code
- The wisp is burned after pickup
- Sling should work for any role (crew, polecat, deacon)


Test Patrol Parent

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

Original description:
Test parent for Christmas Ornament pattern


Digest: mol-deacon-patrol

Patrol cycle 13: all healthy


Digest: mol-deacon-patrol

Patrol 10: All healthy


Move disk 1: B → C

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


Prevent aspect self-matching (infinite recursion)

Aspects should only match original steps, not steps inserted by the same aspect application. Document this and implement guard during cooking. Without this, a pointcut like *.implement that inserts security-prescan could match its own insertion infinitely.


Move disk 1: B → C

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 20: All healthy - handoff threshold reached


Move disk 2: C → B

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


Outpost CLI commands: gt outpost list/status/add

## Overview

CLI commands for managing outposts.

## Commands

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

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

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

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

# Remove outpost
gt outpost remove <name>

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

## Files

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

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


Digest: mol-deacon-patrol

Patrol 121: All healthy, no callbacks, 3 convoys tracking


detectSender() doesn't recognize crew workers

## Problem

`detectSender()` in mail.go only detects polecats, not crew workers.

## Current Code (line 445)

```go
// If in a rig's polecats directory, extract address
if strings.Contains(cwd, "/polecats/") {
    // extract rig/polecat
}

// Default to mayor
return "mayor/"
```

## Symptom

Emma (crew worker at `/Users/stevey/gt/beads/crew/emma`) runs:
- `gt mail inbox` → checks `mayor/` inbox (wrong!)
- Should check `beads/emma` or `beads/crew/emma`

## Fix

Add crew detection:
```go
// If in a rig's crew directory, extract address
if strings.Contains(cwd, "/crew/") {
    parts := strings.Split(cwd, "/crew/")
    if len(parts) >= 2 {
        rigPath := parts[0]
        crewName := strings.Split(parts[1], "/")[0]
        rigName := filepath.Base(rigPath)
        return fmt.Sprintf("%s/%s", rigName, crewName)
    }
}
```

## Also Check

- `gt prime` correctly detects role, so there may be another detection function that works
- Should unify detection logic


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 5: All healthy


Digest: mol-deacon-patrol

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


Work on ga-lzh: Add gt witness attach command. Allow atta...

Work on ga-lzh: Add gt witness attach command. Allow attaching to witness session for a rig, similar to gt mayor attach. When done, submit MR (not PR) to integration branch for Refinery.


Load context

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

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


Move disk 1: C → A

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


Move disk 1: C → A

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


Merge: gt-h6eq.1

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


Digest: mol-deacon-patrol

Patrol cycle 8: All quiet.


Witness sends HEALTH_OK mail to mayor on every deacon ping

## Problem

When Deacon sends HEALTH_CHECK nudges to Witnesses, the Witness Claude sessions
respond by sending 'HEALTH_OK' mail to mayor/. This floods the mayor inbox.

## Current behavior

Deacon: gt nudge gastown/witness 'HEALTH_CHECK'
Witness: gt mail send mayor/ -s 'HEALTH_OK witness' -m 'OK'

This happens every patrol cycle (~30s).

## Expected behavior

Witnesses should NOT send mail responses to routine health checks.

## Fix

Update witness priming to explicitly say 'do not mail on HEALTH_CHECK nudges'.


gt mail read: Support numeric indices for message ID

Allow 'gt mail read 1' to read the first message in inbox.

Current behavior requires full message ID like 'msg-abc123'.
Should support:
- Numeric index: 'gt mail read 1' reads first/newest message
- Partial ID match: 'gt mail read abc' matches 'msg-abc123'

This is a UX improvement - agents frequently type 'gt mail read 1'.


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 nuke: Check if work is on main, not just 'pushed'

## Problem

After Refinery merges a branch and deletes it, the polecat's local branch shows 'unpushed commits' relative to the now-gone tracking branch. This blocks safe nuke even though the work IS on main.

## Current Behavior

```
$ gt polecat nuke gastown/dementus
Error: has 1 unpushed commit(s)
```

But the commit IS already on main (via squash merge).

## Proposed Fix

In nuke safety check (`internal/cmd/polecat.go` or similar):

1. Check if local HEAD commit content is on main (not just if pushed to tracking branch)
2. If commit SHA or equivalent changes are on main → safe to nuke
3. Only block if there's genuinely unpushed/unmerged work

## Implementation Options

A. Check if HEAD is ancestor of origin/main (commit-based)
B. Check if diff between HEAD and main is empty (content-based)
C. Both: fast ancestor check, fallback to diff check

Option A is faster but misses squash merges. Option B is slower but catches all cases.


Digest: mol-deacon-patrol

Patrol 58: All healthy


mol-deacon-patrol


Digest: mol-deacon-patrol

P15: stable


Move disk 2: C → B

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


Move disk 3: A → B

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


Digest: mol-deacon-patrol

Patrol 5: all clear


Digest: mol-deacon-patrol

Patrol 6


Deacon health checks too frequent - disturbs idle agents

Deacon is sending health checks to mayor every few seconds even when idle. This defeats the purpose of the patrol system - agents should NOT be disturbed when there's nothing going on.

Proposed fix:
1. Reduce health check frequency (e.g., every 60s instead of every 5s)
2. Or: Only health check agents that have active work (hooked molecules)
3. Or: Mayor shouldn't be health-checked at all since it's human-managed

The deacon should be silent/invisible when the town is healthy.


Witness: Update polecat monitoring for ephemeral model

Update Witness to handle truly ephemeral polecats.

## Current Behavior
- Witness monitors polecats until MR merged
- 'Rebase needed' mail sent to polecats

## New Behavior
- Witness marks polecat as 'recyclable' after MR submit
- Witness can dispatch conflict-resolution tasks
- Witness doesn't wait for merge to recycle polecat

## Changes to mol-witness-patrol.formula.toml
- Detect 'MR submitted' state
- Mark polecat recyclable
- Handle conflict-resolution dispatch

## Polecat States
```
spawning → working → mr_submitted → recyclable → recycled
```

## Considerations
- Don't recycle sandbox until branch pushed
- Or: Keep sandbox, just recycle session


Parameterize 'read org docs' step in polecat workflows

## Problem

The mol-polecat-chrome formula has hardcoded paths to strategic docs:
- ~/gt/docs/hop/CONTEXT.md
- ~/gt/docs/PRIMING.md

This limits reusability across different projects/organizations.

## Solution

Add a `context_docs` variable to the formula that takes a list of document paths:

```toml
[vars.context_docs]
description = "Paths to organizational context documents to read before design"
default = ["~/gt/docs/hop/CONTEXT.md", "~/gt/docs/PRIMING.md"]
```

## Usage at cook/wisp time

```bash
# Use defaults
gt sling gt-abc gastown -q chrome

# Override for different project
gt sling gt-abc gastown -q chrome   --var context_docs="docs/ARCHITECTURE.md,docs/PRINCIPLES.md"
```

## Step template

The step description would interpolate the paths:

```toml
[[steps]]
id = "read-strategic-context"
title = "Read organizational context documents"
description = """
Read the following strategic context documents before designing:

{{#each context_docs}}
- {{this}}
{{/each}}

These contain the vision, principles, and constraints that should guide your work.
"""
```

## Considerations

1. How to handle the array in TOML var syntax?
2. Should this be a reusable step fragment or inline in chrome?
3. Default paths should work for Gas Town but be overridable

## Related
- mol-polecat-chrome.formula.toml (current hardcoded implementation)


Digest: mol-deacon-patrol

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


Crew worker beads-dave 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


Digest: mol-deacon-patrol

Patrol 6: All healthy


Merge: dag-mjtm8k85

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


Digest: mol-deacon-patrol

Cycle 194: Nominal


Digest: mol-deacon-patrol

Patrol OK: town quiet


mol progress: track dynamically bonded children

Extend `gt mol progress` to show dynamically bonded children.

## Current Behavior

```
gt mol progress gt-abc
```

Shows progress through pre-defined steps from InstantiateMolecule.

## New Behavior

Also show dynamically bonded children:

```
📊 Progress: mol-witness-patrol (gt-abc)

  Steps (9):
    ✓ inbox-check
    ✓ check-refinery
    ✓ load-state
    ◐ survey-workers (bonded 3 children)
    ○ aggregate (WaitsFor: all-children)
    ○ save-state
    ○ generate-summary
    ○ context-check
    ○ burn-or-loop

  Bonded Children (3):
    ✓ arm-toast (5/5 steps)
    ◐ arm-nux (3/5 steps)
    ○ arm-furiosa (0/5 steps)

  Progress: 4/9 steps, 3 arms (1 complete, 1 in-progress, 1 pending)
```

## Implementation

1. Find children with bonded_to: <parent-id> in description
2. Recursively get progress for each bonded child
3. Aggregate into parent progress display