Mol Mall: Formula marketplace and aspect composition

## Summary

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

## Key Insight

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

## Architecture

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

## Formula Types

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

## Aspect Composition (New Cooking Capability)

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

Aspects declare injection points:

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

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

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

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

## The Mall Index

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

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

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

## Implementation Phases

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

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

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

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

## Open Questions

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

## Deferred Until

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

Then the mall becomes valuable for sharing patrol customizations.

## Supersedes

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

## Related

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

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


Refactor: Move formula source of truth to internal/formula/formulas/

## Problem

.beads/formulas/ is tracked in git but polecats using redirects see all formulas as deleted.
The internal/formula/formulas/ directory is already tracked (for embedding).

## Current flow
1. Edit .beads/formulas/ (source of truth)
2. Run go generate ./... → copies to internal/formula/formulas/
3. Build embeds from internal/formula/formulas/
4. ProvisionFormulas() creates .beads/formulas/ from embedded

## Proposed fix
1. Make internal/formula/formulas/ the ONLY tracked formula location
2. Remove .beads/formulas/ from git tracking
3. ProvisionFormulas() already handles runtime provisioning
4. Developers edit internal/formula/formulas/ directly

## Why this fixes polecat tracking
Polecats using redirects won't have .beads/formulas/ tracked, eliminating the deleted entries.


Merge: capable-mjw47ef9

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


Session ended: gt-gastown-crew-gus


MessagingConfig: Add Type field for schema consistency

MessagingConfig lacks a Type field that other config types have (TownConfig has 'town', RigConfig has 'rig', etc). Add Type: 'messaging' for consistency.


gt start --all leaves crew 'running' but 'dead'

dispatched_by: mayor

In start.go, startConfiguredCrew() (line 265) only checks t.HasSession() but doesn't verify Claude is alive with t.IsClaudeRunning(). Compare to runStartCrew() (lines 774-785) which correctly checks IsClaudeRunning and restarts Claude if dead. Fix: add the same IsClaudeRunning check to startConfiguredCrew, restart Claude with BuildCrewStartupCommand if dead.

Fixed: added IsClaudeRunning check to startConfiguredCrew(), restarts Claude if session exists but Claude is dead


Merge: dementus-mjw46vz4

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

All commits already on main - duplicate MR


Session ended: gt-gastown-crew-max


Merge: morsov-1766966180179

branch: polecat/morsov-1766966180179
target: main
source_issue: morsov-1766966180179
rig: gastown


Merge: imperator-mjz958gg

branch: polecat/imperator-mjz958gg
target: main
source_issue: imperator-mjz958gg
rig: gastown
agent_bead: gt-gastown-polecat-imperator
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Merge: road-warrior

branch: polecat/road-warrior-mk0vt2ef
target: main
source_issue: road-warrior
rig: gastown
agent_bead: gt-gastown-polecat-gus
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


mol-sync-workspace: Add vars for build/test commands

Added build_command and test_command variables to mol-sync-workspace formula with template placeholders


Digest: mol-deacon-patrol

Patrol cycle 4: All healthy


Digest: mol-deacon-patrol

Patrol 248 complete: no incidents


Digest: mol-deacon-patrol

Patrol cycle 3: All healthy


Digest: mol-deacon-patrol

Patrol 14: Routine


Merge: dementus-mjto0502

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


INVESTIGATE: Patrol frequency and reliability

During shutdown cleanup, several issues were found that should have been caught by patrols:
- 128 wisps in main beads
- 34 stale hooked handoffs
- Many dead polecats
- Accumulated unread mail in witness/refinery inboxes

Questions:
1. How often are deacon/witness patrols actually running?
2. Are they completing successfully or dying mid-patrol?
3. Is the daemon respawning them properly?
4. Are there logs showing patrol activity?

Check:
- gt deacon patrol logs
- Witness patrol frequency
- Daemon health/respawn behavior

This may indicate patrol infrastructure issues rather than just missing logic.

Not a patrol issue - root cause is digest->wisp dependencies causing export pollution (see gt-de324)


mol-gastown-boot: Mayor-driven town bootstrap

Mayor bootstraps Gas Town via a verification-gated lifecycle molecule.

## Vision

When user says "boot up gas town", Mayor slings `mol-gastown-boot` and executes it.
Each step has **action + verification** - steps stay open until outcome is confirmed.

## Key Principles

1. **No daemon-based timeouts** - Mayor keeps trying until verified
2. **Verification-gated steps** - Not "command ran" but "outcome confirmed"
3. **gt peek for verification** - Capture session output to detect stalls
4. **gt nudge for recovery** - Reliable message delivery to unstick agents
5. **Parallel where possible** - Witnesses can start in parallel
6. **Ephemeral execution** - Boot is a wisp, squashed to digest

## Proto Catalog

Town maintains a catalog of protos at `~/gt/molecules/`:

```
~/gt/molecules/
├── lifecycle/
│   ├── gastown-boot/       # Full town bootstrap
│   ├── rig-spinup/         # Add a rig at runtime
│   ├── rig-spindown/       # Remove a rig gracefully
│   └── agent-restart/      # Restart single agent
├── patrol/
│   ├── deacon-patrol/      # Deacon health loop
│   ├── witness-patrol/     # Witness polecat loop
│   └── refinery-patrol/    # Refinery merge loop
└── work/
    ├── polecat-work/       # Standard issue workflow
    ├── code-review/        # Pluggable review
    └── feature/            # Feature development
```

## mol-gastown-boot Structure

```
mol-gastown-boot (proto)
├── ensure-daemon       # Verify daemon running
├── ensure-deacon       # Start deacon, verify patrol active
├── ensure-witnesses    # Parallel: all rig witnesses
│   ├── ensure-gastown-witness
│   └── ensure-beads-witness
├── ensure-refineries   # Parallel: all rig refineries
│   ├── ensure-gastown-refinery
│   └── ensure-beads-refinery
└── verify-town-health  # Final gt status check
```

## Step Template

Each step in description includes action + verification:

```markdown
## Step: ensure-deacon

### Action
gt deacon start

### Verify
1. Session gt-deacon exists: `tmux has-session -t gt-deacon`
2. Not stalled: `gt peek deacon/` does NOT show "> Try"
3. Recent heartbeat: deacon/heartbeat.json < 2 min old

### On Stall
gt nudge deacon/ "Start patrol."
Wait 30s, re-verify.

### On Fail
Log error, continue to next step (town can run with degraded deacon)
```

## Event-Triggered Lifecycle

Beyond manual slinging, events can trigger lifecycle wisps:

| Event | Triggers |
|-------|----------|
| `gt town start` | mol-gastown-boot wisp |
| `gt rig add <name>` | mol-rig-spinup wisp |
| `gt rig remove <name>` | mol-rig-spindown wisp |
| Agent crash detected | mol-agent-restart wisp |

## Parameterization (Future)

For rig-spinup/spindown, need to pass rig name:

```bash
gt sling rig-spinup mayor/ --param rig=newproject
```

Molecule steps interpolate `${rig}` in their descriptions.

## Related Issues

- gt-lx3n: Witness startup bond
- gt-j6s8: Refinery startup bond
- gt-rana: Patrol System epic
- gt-sye: Mayor startup protocol


Implement verification patterns for boot steps

Define and implement the verification logic Mayor uses.

## Verification Utilities

Mayor needs to check:

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

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

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

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

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

Pattern: `⏺` indicates Claude is executing tools.

## Mayor Execution Pattern

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

No hard timeout - Mayor keeps trying with increasing backoff.


Create molecules catalog directory structure

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

## Structure

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

## PROTO.md Format

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

# mol-gastown-boot

Town bootstrap molecule.

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

## Catalog Loading

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

This enables file-based proto development with beads tracking.


Add parallel step support to molecules

Enable steps to run in parallel within a molecule.

## Current State

Molecules have linear step dependencies via "Needs:" directive.
Steps run sequentially.

## Proposed Change

Add parallel grouping:

```markdown
## Step: ensure-witnesses
Parallel: true

### Sub-steps
- ensure-gastown-witness
- ensure-beads-witness
```

Or via frontmatter:

```yaml
---
parallel: [ensure-witnesses, ensure-refineries]
---
```

Steps in parallel group:
- Start simultaneously
- Parent step closes when all children complete
- Failures in one dont block others

## Implementation

1. Parse parallel directive in proto
2. When bonding, create child steps with same dependency
3. Executor spawns parallel children concurrently
4. Track completion, close parent when all done

## For Mayor Bootstrap

Mayor can check all witnesses in parallel, then all refineries,
rather than sequentially. Faster boot time.


Add event-triggered lifecycle wisps

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

## Event → Wisp Mapping

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

## Implementation

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

## Alternative: Explicit Sling

Keep commands simple, require explicit:

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

This is more transparent - user sees the sling happen.

## Recommendation

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


Design molecule parameterization

Enable protos to accept parameters for customization.

## Use Cases

1. rig-spinup needs rig name: `gt sling rig-spinup --param rig=newproject`
2. agent-restart needs agent: `gt sling agent-restart --param agent=gastown/witness`
3. code-review needs scope: `gt sling code-review --param scope=src/auth/`

## Proposed Syntax

### In Proto

```markdown
## Step: create-rig-structure
mkdir -p ~/gt/${rig}/refinery ~/gt/${rig}/witness
```

### In Sling

```bash
gt sling rig-spinup mayor/ --param rig=newproject --wisp
```

### In Bonded Molecule

Interpolation happens at bond time. Step descriptions have concrete values.

## Implementation

1. Proto declares params in frontmatter: `params: [rig]`
2. gt sling validates required params provided
3. bd mol bond receives params, interpolates descriptions
4. Bonded molecule has concrete step text

## Edge Cases

- Missing required param → error
- Unused param → warning
- Param in step title → interpolate there too


Update Mayor startup protocol for bootstrap

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

## Current Protocol

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

## Enhanced Protocol

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

## Trigger Phrases

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

## Execution

Mayor runs the molecule manually (not via subagent):

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

## CLAUDE.md Update

Add to Mayor CLAUDE.md:

```markdown
## Bootstrap Command

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


Digest: mol-deacon-patrol

Patrol 20: All healthy. Handoff after 20 cycles.


Digest: mol-deacon-patrol

Patrol 19: all healthy


Session ended: gt-gastown-crew-joe


Convoy shows wrong assignee after re-sling

When work is re-slung to a new polecat, convoy status still shows the original assignee.

Example: gt-3jnnu was originally slung to bullet, then re-slung to toecutter. Convoy may still show [bullet].

Need to verify:
1. Does convoy update assignee on re-sling?
2. Is this just stale display or actual tracking issue?

Low priority - cosmetic if work is actually running correctly.

Fixed BEADS_DIR override for rig-level beads in sling.go and added --no-daemon to convoy bd show calls


Digest: mol-deacon-patrol

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


Session ended: gt-gastown-crew-george


Digest: mol-deacon-patrol

Patrol 82: All agents healthy, quiet cycle


Digest: mol-deacon-patrol

Patrol 134: All healthy


Merge: gt-594l2

branch: polecat/morsov-1766966180179
target: main
source_issue: gt-594l2
rig: gastown


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

Cycle 5: healthy


Session ended: gt-gastown-ace


Digest: mol-deacon-patrol

Patrol 1: All healthy, no messages, no orphans


Digest: mol-deacon-patrol

Patrol 4: Quiet


Digest: mol-deacon-patrol

Patrol 8: Quiet


Digest: mol-deacon-patrol

Patrol cycle 20: all healthy, handing off


Session ended: gt-gastown-corpus

Bulk cleanup of stale session-ended events (gt-8tc1v)


gt polecat done should auto-stop running session

Currently 'gt polecat done' fails if session is running, requiring a separate 'gt session stop' first. This is unnecessary friction - done should just stop the session automatically since that's always what you want.


Digest: mol-deacon-patrol

Patrol cycle 20: All agents healthy, handoff threshold reached


Digest: mol-deacon-patrol

Patrol 20: All healthy, 17 sessions


Witness checks wrong remote for merge verification

## Problem

Witness patrol checks `origin/main` to verify if polecat commits are merged, but in multi-remote setups the code lives on a different remote (e.g., `gastown/main`).

## Evidence

From witness tmux output:
```
git merge-base --is-ancestor 9876a962 origin/main && echo "MERGED" || echo "NOT MERGED"
→ NOT MERGED - preserve
```

But the commit IS merged to `gastown/main`:
```
git log gastown/main | grep 9876a962
→ 9876a962 perf: Batch and parallelize convoy worker lookups
```

## Root Cause

witness/rig has multiple remotes:
- `origin` → stevey-gt.git (beads sync)
- `gastown` → gastown.git (actual code)

Witness hardcodes `origin/main` instead of detecting the correct code remote.

## Fix

Either:
1. Use rig config to specify the code remote name
2. Check all remotes for the commit
3. Standardize remote naming across all clones


Digest: mol-deacon-patrol

Patrol 206: All nominal


Merge: nux-1767138828269

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


gt crew add: role_bead field references non-existent bead

## Problem

When `gt crew add` creates an agent bead (e.g., `gt-crew-gastown-grip`), it sets:
```
role_bead: gt-crew-gastown-grip-role
```

This is WRONG. It creates per-instance role bead references that don't exist.

## Correct Pattern

Role beads are SHARED templates defining what a role IS. Agent beads reference them:

| Role Type | Role Bead (shared) | Agent Bead (per-instance) |
|-----------|-------------------|---------------------------|
| Mayor | gt-mayor-role | gt-mayor |
| Deacon | gt-deacon-role | gt-deacon |
| Witness | gt-witness-role | gt-witness-<rig> |
| Refinery | gt-refinery-role | gt-refinery-<rig> |
| Crew | gt-crew-role | gt-crew-<rig>-<name> |
| Polecat | gt-polecat-role | gt-polecat-<rig>-<name> |

## Current State

Working correctly:
- gt-mayor → gt-mayor-role ✅
- gt-witness-gastown → gt-witness-role ✅
- gt-refinery-gastown → gt-refinery-role ✅

Broken:
- gt-deacon → gt-deacon-role (bead doesn't exist)
- gt-crew-* → gt-crew-<rig>-<name>-role (wrong pattern, beads don't exist)
- gt-polecat-* → (not set at all)

## Code Locations

1. `internal/cmd/crew_add.go:91` - sets `RoleBead: crewID + "-role"`
   Should be: `RoleBead: "gt-crew-role"`

2. `internal/polecat/manager.go:220,426` - doesn't set RoleBead
   Should set: `RoleBead: "gt-polecat-role"`

## Fix Required

1. Create missing role beads: gt-crew-role, gt-polecat-role, gt-deacon-role
2. Fix crew_add.go to use shared gt-crew-role
3. Fix polecat/manager.go to use shared gt-polecat-role
4. Update existing crew agent beads to point to gt-crew-role

Fixed. Created shared role beads (gt-crew-role, gt-polecat-role, gt-deacon-role). Fixed code to reference shared role beads. Updated existing crew agent beads via bd slot set.


Session ended: gt-gastown-refinery


Digest: mol-deacon-patrol

Patrol 11 complete


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

Implemented witness activity events: patrol_started, polecat_checked, polecat_nudged, escalation_sent, patrol_complete. Added gt activity emit command for CLI access. Events write to ~/gt/.events.jsonl.


Session ended: gt-gastown-nux


Digest: mol-deacon-patrol

Patrol #4: All systems nominal


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

Implement condition checking for each await type.

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

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

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


Digest: mol-deacon-patrol

Patrol 3: routine, all healthy


Digest: mol-deacon-patrol

Patrol 18 complete


MessagingConfig: Fix error message inconsistency in validation

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


Session ended: gt-gastown-crew-joe


Digest: mol-deacon-patrol

Patrol 74: Routine


Digest: mol-deacon-patrol

Cycle 186: Nominal


Digest: mol-deacon-patrol

Patrol 5: all healthy


Cross-rig agent identity detection

## Problem

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

## Root Cause

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

## Scope

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

## Fix Strategy

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

All sub-tasks complete: gt sling dot resolution (gt-hldpv), gt hook cross-rig identity (gt-5d7eh), gt peek cross-rig paths (gt-yud21) - all fixed


Digest: mol-deacon-patrol

Patrol 9: Routine


Deacon Patrol

Mayor's daemon patrol loop for handling callbacks, health checks, and cleanup.

Duplicate patrol molecule beads - keeping gt-t5i07, gt-8ynws, gt-kt9qq


Digest: mol-deacon-patrol

Routine patrol, town stable


Digest: mol-deacon-patrol

Patrol 157: All healthy


Session ended: gt-gastown-crew-jack


Phase 4: Migration script for existing installations

## Goal

Provide migration for existing installations with gt-* agent beads in rig beads.

## Approach

Create gt doctor --fix logic or standalone migration:

1. Detect old agent beads in rig beads (gt-mayor, gt-deacon, gt-*-role)
2. Create new agent beads in town beads (hq-mayor, hq-deacon, hq-*-role)
3. Copy relevant state (agent_state, hook_bead, etc.)
4. Mark old beads as migrated (add migration note)
5. Update any references

## Commands

Option A: Part of gt doctor --fix
Option B: Standalone gt migrate-agents command

## Safety

- Dry-run mode by default
- Preserve old beads (don't delete)
- Validate new beads created successfully
- Log all changes

## Testing

- Run on existing ~/gt installation
- Verify hq-* beads created in town beads
- Verify agent lookups still work

Migration command implemented and verified working. Already committed in 0b88dc20.


Implement gt convoy add command

Add the 'add' subcommand to convoy for adding issues to existing convoys.

SYNTAX:
gt convoy add <convoy-id> <issue-id> [issue-id...]

BEHAVIOR:
1. Validate convoy exists
2. Add 'tracks' dependency for each issue
3. If convoy is closed, reopen it automatically
4. Print confirmation

IMPLEMENTATION:
File: internal/cmd/convoy.go
Add: convoyAddCmd as subcommand

Example:
gt convoy add hq-cv-abc gt-new-issue
# -> Added gt-new-issue to convoy hq-cv-abc

gt convoy add hq-cv-abc gt-followup  # convoy was closed
# -> Reopened convoy hq-cv-abc
# -> Added gt-followup to convoy hq-cv-abc

Verified implementation: build passes, help works, add/reopen tested


Merge: nux-1767087680976

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


Digest: mol-deacon-patrol

Patrol 7 complete. All healthy.


[Refactor] Extract bd command wrapper package

Multiple exec.Command("bd", ...) calls scattered across rig/manager.go and crew/manager.go:

- rig/manager.go: bd init (x2), bd migrate, bd mol seed, bd list, bd create
- crew/manager.go: bd sync

Should create internal/bdclient package with typed methods:
  bdclient.Init(dir, prefix string) error
  bdclient.Sync(dir string) error
  bdclient.Create(dir string, opts CreateOpts) error

Benefits: consistent error handling, easier testing/mocking, single place for bd interaction patterns.


Migrate from .claude/commands/ to .claude/skills/ format

## Summary

Claude Code v2.0+ deprecated `.claude/commands/` in favor of `.claude/skills/`.
All gastown workers currently have `.claude/commands/handoff.md` which no longer loads.

## Current State

- Workers have `.claude/commands/handoff.md` (deprecated, not loading)
- `/handoff` skill is unavailable to agents

## Fix Required

1. Create `.claude/skills/handoff/SKILL.md` with proper frontmatter format
2. Remove deprecated `.claude/commands/handoff.md` files
3. Update worker setup process to use skills format

## Skill Format

```yaml
---
name: handoff
description: >
  Hand off to a fresh Claude session. Work continues from hook.
allowed-tools: "Bash(gt handoff:*),Bash(gt mail send:*)"
version: "1.0.0"
---
```

## Affected Locations

- ~/gt/gastown/crew/*/claude/commands/handoff.md (all crew workers)
- ~/gt/gastown/mayor/rig/.claude/commands/handoff.md
- ~/gt/gastown/refinery/rig/.claude/commands/handoff.md

## Reference

- beads already migrated: `.claude/skills/handoff/SKILL.md`
- User-wide skill added: `~/.claude/skills/handoff/SKILL.md`

Migrated handoff skill to .claude/skills/ format for 13 gastown locations


Review PR #83: Update dependencies

Approved PR #83: Update dependencies. Verified build and tests pass locally. All changes are minor/patch version bumps with no breaking changes.


gt doctor: add bd daemon status check

Add check for daemon running. Add check for database fingerprint. --fix should be able to migrate (bd migrate --update-repo-id) and restart daemon.

Implemented repo-fingerprint check in gt doctor


Merge: corpus-mk0r5ick

branch: polecat/corpus-mk0r5ick
target: main
source_issue: corpus-mk0r5ick
rig: gastown
agent_bead: gt-gastown-polecat-gus
retry_count: 0
last_conflict_sha: null
conflict_task_id: null

Branch polecat/corpus-mk0r5ick no longer exists - work not on main, unverifiable


Cost tracking v1: tmux scraping + ledger

## Overview
Implement basic cost tracking for Gas Town agents using tmux scraping.

## Scope

### 1. Live cost scraping
- `gt costs` command that:
  - Finds all Claude Code tmux sessions (polecat-*, witness-*, refinery-*, mayor-*)
  - Runs `tmux capture-pane -t <session> -p`
  - Extracts cost with regex: `\$[0-9]+\.[0-9]+`
  - Displays table: session | role | cost

### 2. Cost ledger
- File: `~/.gt/costs.jsonl`
- Schema: `{session_id, role, rig, cost_usd, started_at, ended_at, work_item}`
- Written on session end (SessionEnd hook integration)

### 3. Aggregation commands
- `gt costs` - Live costs from running sessions
- `gt costs --today` - Today's total from ledger
- `gt costs --week` - This week's total
- `gt costs --by-role` - Breakdown by role (polecat, witness, etc.)
- `gt costs --by-rig` - Breakdown by rig

### 4. Hook integration
- Add SessionEnd hook handler that:
  - Captures final cost
  - Writes to ledger
  - Includes work_item if attached

## Non-goals (v2)
- Per-convoy attribution
- Cost warnings/budgets
- Historical trends
- Deacon integration for periodic capture

## Reference
- GitHub issue #24
- docs/agent-compatibility.md (future direction)

Implemented cost tracking v1 with live scraping, ledger, and hook integration


Digest: mol-deacon-patrol

Patrol 19: All clear


Wire up gt costs record to Stop hook

## Task

Add `gt costs record` to the Claude Code Stop hook so session costs are automatically recorded when sessions end.

## Context

`gt costs record` is implemented (gt-f7jxr) but not yet wired up. Currently, session costs are never actually recorded to beads because nothing calls this command.

## Implementation

Add to `~/.claude/settings.json` (or project settings):

```json
{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "gt costs record --session \$GT_SESSION"
          }
        ]
      }
    ]
  }
}
```

Alternatively, add to the session-end hook script if we use that pattern.

## Considerations

1. **Session name**: Need to pass the tmux session name. Could use:
   - $GT_SESSION env var (if set by session-start)
   - Parse from hook input JSON (session_id field)
   - Infer from tmux (risky if multiple sessions)

2. **Work item**: Optionally pass `--work-item` if we can determine what was being worked on

3. **Template update**: May need to update Gas Town templates that generate settings.json

## Acceptance Criteria

- [ ] Stop hook calls `gt costs record`
- [ ] Session name passed correctly
- [ ] Costs appear in `gt costs --today` after session ends
- [ ] Templates updated if needed

## References

- gt-f7jxr (cost tracking v2)
- gt-nrpiq (cost tracking v1)

Stop hook wired up - session costs now recorded automatically when sessions end


Session ended: gt-gastown-crew-gus


Merge: rictus-1767087768853

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


Digest: mol-deacon-patrol

Cycle 181: All agents healthy, processed 3 health acks, 7 doctor warnings noted (non-critical), no incidents


Digest: mol-deacon-patrol

Cycle 4: All healthy


Digest: mol-refinery-patrol

Patrol: merged 5 branches, closed 1 already-merged (dementus). No issues.


Digest: mol-deacon-patrol

Quick patrol: no messages, all healthy


Digest: mol-deacon-patrol

Patrol 28: all quiet


gt done: Capture session_id in issue close for CV attribution

## Context

Per decision 009-session-events-architecture.md, work attribution should happen
by capturing session_id on beads mutations. This enables querying "what work
did this session do?" for entity CV building.

## Implementation

When gt done closes an issue, pass CLAUDE_SESSION_ID to bd close:

```go
// In done.go
sessionID := os.Getenv("CLAUDE_SESSION_ID")
if sessionID != "" {
    // Pass to bd close via --session flag or env var
}
```

## Acceptance Criteria

- [ ] gt done passes session_id to bd close
- [ ] Issue close events include session attribution
- [ ] Works for gt mol complete as well

## Dependencies

- Beads must support session_id on issue close (bd-* issue)

## Related

- docs/hop/decisions/009-session-events-architecture.md

Implemented session_id passing to all bd close calls via CLAUDE_SESSION_ID env var


Digest: mol-deacon-patrol

Patrol cycle 11


Digest: mol-deacon-patrol

Patrol 41 complete: All agents healthy, 2 convoys in progress (Hanoi, Messaging), health pings sent, 1 idle dog


Digest: mol-deacon-patrol

Patrol 41: All healthy, 3 rigs, 3W/3R pinged, no incidents


Add gt mail clear command for bulk inbox clearing

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

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

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

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

Added gt mail clear command for bulk inbox clearing


Digest: mol-deacon-patrol

Patrol 150 complete


Merge: prime-mk0aw9ai

branch: polecat/prime-mk0aw9ai
target: main
source_issue: prime-mk0aw9ai
rig: gastown
agent_bead: gt-gastown-polecat-prime
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Digest: mol-deacon-patrol

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


Session: gt-gastown-test completed gt-f7jxr


Digest: mol-deacon-patrol

Cycle 4: healthy, refinery started


Digest: mol-deacon-patrol

Cycle 194: Nominal


Session ended: gt-gastown-crew-jack


Digest: mol-deacon-patrol

Patrol cycle 9: All healthy.


Digest: mol-deacon-patrol

Cycle 12: quiet


Digest: mol-deacon-patrol

Patrol 15: all clear


Digest: mol-deacon-patrol

Patrol 16: quiet


Test Patrol Parent

Test parent for Christmas Ornament pattern


Session ended: gt-gastown-crew-joe


Merge: capable-mjxm03qy

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


gt crew add: CLAUDE.md customization leaves git dirty

When gt crew add generates a customized CLAUDE.md for crew workers, it differs from the repo version (Crew Worker Context vs Polecat Context, personalized footer). This leaves the git state 'dirty'.

Options:
1. Add CLAUDE.md to .gitignore in crew workspaces
2. Auto-commit the customized CLAUDE.md locally
3. Store crew CLAUDE.md content elsewhere (e.g., .claude/CLAUDE.md)

Current behavior is functional but 'gt crew list' shows 'Git: dirty' for new crew.

Found during: adding crew workers grip, fang, wolf


Digest: mol-deacon-patrol

Patrol cycle 21 complete. Detected 2 orphaned polecats (nux, rictus), escalated to Mayor. All 3 rigs healthy (beads, gastown, wyvern). No convoys, gates, or plugins.


Mail inbox from witness/refinery dirs shows Mayor inbox

When running `gt mail inbox` from the witness or refinery directories, it shows the Mayor's inbox instead of the agent's own inbox.

Reproduction:
```
$ cd ~/gt/beads/witness && gt mail inbox
📬 Inbox: mayor/ (1 messages, 1 unread)
  ● 🤝 HANDOFF: Swarm session complete...
```

Expected: Should show beads/witness inbox

Likely cause: The cwd-based identity resolution isn't recognizing witness/refinery as valid mail identities, so it falls back to Mayor.

Fixed by falling back to cwd-based detection when GT_ROLE is not set


Digest: mol-deacon-patrol

Patrol 157 complete


Day 3.7: Witness pings Deacon for second-order monitoring

Add second-order monitoring: Witnesses monitor the Deacon.

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

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

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

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

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

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


Session test with rig


Merge: nux-mjtj9d8q

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


Digest: mol-deacon-patrol

Patrol cycle 16: All healthy - 8 polecats running (max, jack, dementus, capable, toast, dag + crew). Handing off after 6 cycles.


Session ended: gt-gastown-ace


Add neighbor-check steps to all patrol molecules

Part of the 'Gas Town is a Village' antifragility design.

Every patrol molecule should include optional neighbor-checking:
- Deacon checks Witness and Refinery health
- Witness checks Refinery health
- Refinery checks Witness health
- Polecats can peek other polecats

Use gt peek to check health states.
If stuck neighbor found, can nudge or escalate.

This creates distributed monitoring - no single point of failure.


Digest: mol-deacon-patrol

Patrol cycle 14: All 6 agents healthy


Merge: angharad-mjwjn205

branch: polecat/angharad-mjwjn205
target: main
source_issue: angharad-mjwjn205
rig: gastown
agent_bead: gt-gastown-polecat-angharad


Session ended: gt-gastown-wretched


BUG: Cross-beads slot references silently fail

When slinging work from town beads (hq-*) to a polecat whose agent bead is in rig beads (gt-*), the hook_bead update silently fails.

**Reproduction:**
```
# From mayor (town root):
gt sling hq-oosxt gastown/polecats/nux

# This runs (in updateAgentHookBead):
bd slot set gt-gastown-polecat-nux hook hq-oosxt
# FAILS: can't find hq-oosxt (different beads directory)
# Error is silently ignored!
```

**Result:**
- Agent bead keeps stale hook_bead value
- gt hook shows wrong/old work
- Agent doesn't know what they're actually assigned

**Root cause:**
sling.go line 812-814 silently ignores UpdateAgentState errors:
```go
if err := bd.UpdateAgentState(agentBeadID, "running", &beadID); err != nil {
    // Silently ignore - agent bead might not exist yet
    return
}
```

**Fix options:**
1. Log warnings instead of silent ignore
2. Support cross-beads slot references (store as 'hq-oosxt@town' or similar)
3. Use external: prefix for cross-beads hooks
4. Always store hook in the WORK bead's directory, not agent bead

Discovered during investigation of stale hook issue.

Fixed: Use town root for routing in sling/done, log warnings instead of silent ignore


Session ended: gt-gastown-vuvalini


Digest: mol-deacon-patrol

Patrol 161: All agents healthy, no incidents, 1 dog idle


Session ended: gt-gastown-angharad


Merge: organic-mjwjck2f

branch: polecat/organic-mjwjck2f
target: main
source_issue: organic-mjwjck2f
rig: gastown
agent_bead: gt-gastown-polecat-organic

Stale MR - organic resubmitted as gt-a28hb


Digest: mol-deacon-patrol

P19: stable


Liftoff implementation plan in Beads

## Context

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

## Work Required

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

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

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

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

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

## Deliverable

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

## References

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


gt crew start <rig> [name] | --all - start crew workers

Start crew workers in a rig. Can specify a name to start one, or --all to start all crew members in the rig.

Implemented gt crew start <rig> [name] | --all command


Session ended: gt-gastown-crew-jack


Digest: mol-deacon-patrol

Cycle 300: All healthy, refinery queue 7


gt polecat list: deduce rig from cwd

When running `gt polecat list` from within a rig directory, it should deduce the rig name automatically instead of requiring it as an argument.

Example:
```
cd ~/gt/beads
gt polecat list   # Should work, deducing rig=beads
```

Currently requires explicit rig name or --all flag.


Digest: mol-deacon-patrol

Patrol 11: quick pass


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


ZFC #9: Explicit MR registration instead of branch parsing

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 102: All agents healthy, no incidents


Digest: mol-deacon-patrol

Patrol 100: All healthy. Handing off after 20 patrols.


Digest: mol-deacon-patrol

Patrol 3: Quiet


Session ended: gt-gastown-crew-gus


Session ended: gt-gastown-crew-jack

Bulk cleanup of stale session-ended events (gt-8tc1v)


Digest: mol-deacon-patrol

Patrol 70: Routine


Merge: dementus-1767074970788

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

Branch no longer exists on remote - already merged or cleaned up


Fix gt polecats docs in reference.md

reference.md:211 documents 'gt polecats <rig>' but actual command is 'gt polecat list [rig]'. Already fixed in ~/gt/CLAUDE.md.

Fixed: updated gt polecats to gt polecat list in Go files and templates


Digest: mol-deacon-patrol

Patrol 20: all healthy, handoff threshold reached


Digest: mol-deacon-patrol

Patrol cycle 24: All healthy, no incidents


Session ended: gt-gastown-crew-george


Cache AgentRegistry loading in ResolveAgentConfig

ResolveAgentConfig calls LoadAgentRegistry on every invocation, reloading agents.json from disk each time. Should cache the result after first load.

Added mutex protection, sync-safe initialization, path caching, and ResetRegistryForTesting() helper


Digest: mol-deacon-patrol

Patrol cycle 16: All healthy.


Digest: mol-deacon-patrol

Patrol 19: splendid spawned


Digest: mol-deacon-patrol

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


Merge: ace-mjufugk0

branch: polecat/ace-mjufugk0
target: main
source_issue: ace-mjufugk0
rig: gastown


Create AgentIdentity type for session name parsing

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 6: quick pass


Session ended: gt-gastown-nux


Digest: mol-deacon-patrol

Patrol 14: all healthy


Maintenance: Regular cleanup of closed MR/gate beads

Closed merge-request and gate beads accumulate over time. Need regular cleanup.

## Cleanup Candidates
- type=merge-request with status=closed
- type=gate with status=closed
- type=molecule with status=closed (completed workflows)

## Options
1. **Deacon patrol step** - squash closed MRs periodically
2. **Refinery post-merge** - close and tombstone MR after successful merge
3. **bd doctor check** - warn when stale MR count exceeds threshold

## Consideration
Keep some audit trail? Or just tombstone after N days?


Session ended: gt-gastown-crew-jack


Digest: mol-deacon-patrol

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


Session ended: gt-gastown/crew/joe


Merge: nux-1767073376184

attached_args: Code review this merge request

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

Code review complete. BLOCKED: needs rebase before merge. Stale branch would revert swarm fixes from 10e79789. See comments for details.


Merge: nux-1767079896198

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


Digest: mol-deacon-patrol

Patrol cycle 18: All healthy.


Session ended: gt-gastown-crew-gus


Add unit tests for internal/lock package

attached_args: Lock package tests

Add comprehensive tests for the file locking package.

## Files to create
- internal/lock/lock_test.go

## Test cases to cover
1. Lock() acquires lock successfully
2. Lock() blocks when lock held by another
3. Unlock() releases lock
4. TryLock() returns immediately if locked
5. IsLocked() detects lock state
6. Lock file contains correct PID
7. Stale lock detection (if implemented)

## Acceptance criteria
- [ ] internal/lock/lock_test.go created
- [ ] At least 5 test functions
- [ ] Tests pass: go test ./internal/lock/...
- [ ] Coverage > 70%: go test -cover ./internal/lock/...


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.


Extend gt nudge to support channel:name syntax

Add channel support to internal/cmd/nudge.go.

CURRENT BEHAVIOR:
gt nudge <session> <message> - nudges single session

NEW BEHAVIOR:
gt nudge channel:<name> <message> - nudges all members of channel

IMPLEMENTATION:
1. Detect if target starts with 'channel:'
2. If so, extract channel name
3. Load messaging.json via config.LoadMessagingConfig
4. Look up NudgeChannels[name]
5. Resolve each member pattern to session names (use existing resolution logic)
6. Call t.NudgeSession() for each

PATTERN RESOLUTION:
- Literal: gastown/witness → session name
- Wildcards: gastown/polecats/* → expand via getAgentSessions()
- @groups: @town → expand via parseGroupAddress() patterns

FILE: internal/cmd/nudge.go
TESTS: Add TestNudgeChannel

NOTE: Look at broadcast.go for session enumeration patterns.

Implemented channel:name syntax with pattern resolution and tests


Day 2.6: Define bd agent state command

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol cycle 73: All healthy


Merge: furiosa-mjxc7zq9

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

Branches merged, cleaning up stale MR beads


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)


Digest: mol-deacon-patrol

Patrol 141: All agents healthy, 4 polecats working, no issues


Digest: mol-deacon-patrol

Patrol cycle 16: All 6 agents healthy


Merge: splendid-mjz9oobk

branch: polecat/splendid-mjz9oobk
target: main
source_issue: splendid-mjz9oobk
rig: gastown
agent_bead: gt-gastown-polecat-splendid
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Code Smell: Mailbox struct conflates two modes (legacy vs beads)

The Mailbox struct (mailbox.go:30-36) conflates two distinct operating modes:

```go
type Mailbox struct {
    identity string // beads identity (e.g., "gastown/polecats/Toast")
    workDir  string // directory to run bd commands in
    beadsDir string // explicit .beads directory path (set via BEADS_DIR)
    path     string // for legacy JSONL mode (crew workers)
    legacy   bool   // true = use JSONL files, false = use beads
}
```

Most methods have `if m.legacy { ... } else { ... }` branches:
- List(): listLegacy() vs listBeads()
- Get(): getLegacy() vs getBeads()
- MarkRead(): markReadLegacy() vs markReadBeads()
- etc.

**Recommendation**: Extract an interface and have two implementations:

```go
type MailStore interface {
    List() ([]*Message, error)
    Get(id string) (*Message, error)
    MarkRead(id string) error
    MarkUnread(id string) error
    Delete(id string) error
    // ...
}

type LegacyMailbox struct { ... }  // JSONL implementation
type BeadsMailbox struct { ... }   // beads implementation
```

This would make the code cleaner and easier to test.

Files:
- internal/mail/mailbox.go:30-36, 89-94, 251-267, 269-275, etc.

Severity: low


mol-sync-workspace: Add Refinery-specific inline conflict resolution guidance

Added detailed Refinery-specific conflict resolution guidance to sync-git step in mol-sync-workspace formula


Session ended: gt-gastown-crew-jack


Digest: mol-deacon-patrol

Cycle 187: Nominal


Merge: nux-mjxc8hbs

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

Branch already merged/deleted - orphaned MR


Digest: mol-deacon-patrol

Patrol 37: all quiet


Digest: mol-deacon-patrol

Patrol 15: All healthy


Digest: mol-deacon-patrol

Patrol cycle 2: all healthy, no incidents


Digest: mol-deacon-patrol

Patrol 120: All healthy - session complete


Digest: mol-deacon-patrol

Patrol 10 complete


Add bash/zsh shell completions for gt CLI

Need shell autocompletions for the gt command to improve usability.

Should support:
- Bash completions
- Zsh completions
- Fish completions (nice to have)

Cobra has built-in completion generation:
  cmd.GenBashCompletion()
  cmd.GenZshCompletion()

Need to:
1. Add 'gt completion bash/zsh/fish' command
2. Document installation in README
3. Consider auto-install during 'gt init' or first run

Documented completion install in README (a78fe7e). Cobra provides gt completion bash/zsh/fish.


Digest: mol-deacon-patrol

Patrol cycle 1: All 6 agents healthy, no issues, inbox clean


Digest: mol-deacon-patrol

Patrol 26: furiosa session started, all quiet


Digest: mol-deacon-patrol

Patrol cycle 5: All agents healthy


Digest: mol-deacon-patrol

Patrol 29: all quiet


Digest: mol-deacon-patrol

Patrol 11: routine


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

Patrol 257 complete: no incidents


Day 2.7b: gt rig add creates Witness and Refinery agent beads

Update gt rig add to create agent beads:

1. After initializing rig beads, create:
   - gt-witness-<rig> agent bead (role_type: witness, rig: <rig>, agent_state: idle)
   - gt-refinery-<rig> agent bead (role_type: refinery, rig: <rig>, agent_state: idle)

2. Use bd create --type=agent or internal beads API

Files:
- internal/cmd/rig.go
- internal/rig/manager.go


Plugin: merge-oracle (merge queue analysis)

Example plugin that analyzes changesets before Refinery processes them. Builds overlap graph, classifies disjointness (parallel-safe vs needs-sequencing), uses LLM for semantic complexity, identifies high-risk patterns. Based on merge-orchestration proposal. See docs/architecture.md.


Add --dry-run flag to polecat cleanup command

The polecat cleanup command should support --dry-run to preview what would be cleaned without actually doing it. Currently trying 'gt polecat cleanup --dry-run' returns 'unknown flag: --dry-run'.


Digest: mol-deacon-patrol

Patrol 9


Digest: mol-deacon-patrol

Cycle 5: 2 acks


Digest: mol-deacon-patrol

Patrol cycle 10: All healthy


Session ended: gt-gastown-crew-max


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 19: All 3 rigs healthy. No incidents.


Add isAnnounceAddress() and parseAnnounceName() helpers to router.go

Add announce address detection to internal/mail/router.go.

PATTERN TO FOLLOW:
Look at isListAddress() and parseListName() at lines 53-60 as the template.

IMPLEMENTATION:
1. Add isAnnounceAddress(address string) bool - returns true if address starts with 'announce:'
2. Add parseAnnounceName(address string) string - extracts announce name after 'announce:'
3. Add var ErrUnknownAnnounce = errors.New("unknown announce channel")

FILE: internal/mail/router.go
TESTS: Add tests in internal/mail/router_test.go

Small, focused task - just address detection, not delivery.

Implemented announce address helpers as part of gt-q73h3


Digest: mol-deacon-patrol

Patrol 19: Quiet


Session ended: gt-gastown-crew-jack


Implement git merge logic in Engineer.ProcessMR

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

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

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

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

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

Implemented ProcessMR and ProcessMRFromQueue with full git merge logic: fetch, conflict check, test run, merge, push


Digest: mol-deacon-patrol

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


gt-polecat-gastown-ace

gt-polecat-gastown-ace

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


gt-polecat-gastown-capable

gt-polecat-gastown-capable

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


gt-polecat-gastown-furiosa

gt-polecat-gastown-furiosa

role_type: polecat
rig: gastown
agent_state: done
hook_bead: null
role_bead: null
cleanup_status: clean


gt-polecat-gastown-morsov

gt-polecat-gastown-morsov

role_type: polecat
rig: gastown
agent_state: done
hook_bead: null
role_bead: null


gt-polecat-gastown-nux

gt-polecat-gastown-nux

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


gt-polecat-gastown-rictus

gt-polecat-gastown-rictus

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


gt-polecat-gastown-slit

gt-polecat-gastown-slit

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


gt-polecat-gastown-warboy

gt-polecat-gastown-warboy

role_type: polecat
rig: gastown
agent_state: spawning
hook_bead: null
role_bead: null


Polecat Role Definition

You are a Polecat - an autonomous worker assigned to a specific issue.

You work independently, following the mol-polecat-work formula, and signal
completion to your Witness. You are transient - spawned for work, cleaned up
after completion.

session_pattern: gt-{rig}-{name}
work_dir_pattern: {town}/{rig}/polecats/{name}
needs_pre_sync: true
start_command: export GT_ROLE=polecat GT_RIG={rig} GT_POLECAT={name} BD_ACTOR={rig}/polecats/{name} && claude --dangerously-skip-permissions

default_molecule: mol-polecat-work
capabilities:
  - execute_assigned_work
  - git_operations
  - branch_management
  - completion_signaling

## Core Responsibilities

1. Execute your pinned molecule's steps
2. Maintain clean git state
3. Signal completion via gt done
4. Wait for Witness to handle lifecycle

## You Do NOT

- Push directly to main (Refinery merges)
- Kill your own session (Witness does cleanup)
- Skip verification steps
- Work on anything other than your assigned issue

## Propulsion Principle

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

Your work is defined by your pinned molecule. Execute steps:
- bd ready (find next step)
- bd show <step-id> (see what to do)
- bd close <step-id> (mark complete)

## Completion Protocol

When done:
1. Tests pass: go test ./...
2. COMMIT changes: git add and git commit
3. Push branch: git push -u origin HEAD
4. Close issue: bd close <issue>
5. Sync beads: bd sync
6. Run gt done
7. WAIT: Witness will kill your session

## Communication

Mail your Witness when stuck:
gt mail send <rig>/witness -s "HELP: <problem>" -m "..."


Merge: morsov-1767074381346

attached_args: Code review this merge request

branch: polecat/morsov-1767074381346
target: main
source_issue: morsov-1767074381346
rig: gastown

Already merged: morsov's work (commit 10e79789: Fix swarm not tracking dynamically added workers) is present in main. Branch is ancestor of main - no merge needed.


Digest: mol-deacon-patrol

Patrol cycle 39: All healthy, no incidents


Add GitHub CI workflow for PRs

Gas Town has no CI. Add .github/workflows/ci.yml that runs tests and linter on PRs. Reference beads repo for example.

Added .github/workflows/ci.yml with test, lint, and beads protection jobs


Digest: mol-deacon-patrol

Patrol cycle 8: All 6 agents healthy


Day 2.2: Remove PID/tmux state inference

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

Daemon becomes pure transport layer.

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

Parent: gt-d0jqp

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


Digest: mol-deacon-patrol

Cycle 7: quiet


gt sling: Support batch slinging multiple beads

Currently `gt sling` only accepts one bead at a time:

```
gt sling gt-abc gastown        # works
gt sling gt-abc gt-def gastown # fails: accepts between 1 and 2 arg(s)
```

## Proposed

Allow multiple beads in a single command:
```
gt sling gt-abc gt-def gt-ghi gastown
```

This would spawn a polecat for each bead (or reuse existing ones).

## Use case

Slinging related work from a convoy - want to parallelize without running gt sling N times manually.

Implemented batch slinging: gt sling now accepts multiple beads with a rig target. Each bead gets its own polecat.


Remove StateIdle and idle polecat concept

## Problem

StateIdle is marked deprecated in types.go:24 but still actively used throughout the codebase.
This violates the transient polecat model from PRIMING.md: "Polecats exist only while working."

## Evidence of Heresy

1. StateIdle marked deprecated but not removed
2. manager.go:748 - Get() returns StateIdle when no issue assigned
3. deacon.go:191 - "Scan for idle polecats that should have been nuked"
4. Multiple commands accept/produce idle state

## Correct Model

From PRIMING.md:278: "The sandbox persists; sessions are fresh."

Sandbox exists IFF work exists. There is no idle state:
- Spawn: sandbox created, work assigned
- Work: sessions cycle, sandbox persists
- Done: Witness nukes sandbox

## Changes Required

1. Remove StateIdle from types.go
2. Update Get() to never return idle (if no work, polecat should not exist)
3. Remove zombie scan logic (becomes unnecessary)
4. Update tests that reference StateIdle

Removed StateIdle from polecat/types.go, updated manager.go to use StateDone/StateWorking, removed zombie scan logic from deacon.go, updated tests.


Digest: mol-deacon-patrol

Patrol 75: Routine


Merge: ace-dogs

branch: polecat/ace-dogs
target: main
source_issue: ace-dogs
rig: gastown


Post-work discovery: AI analysis finds follow-on issues

AI analyzes completed work to discover: bugs, punted work, follow-on tasks.

**From VC**: Supervisor.AnalyzeResult() with iterative refinement. ~300 lines.

**Gas Town implementation**: Post-work hook in molecule:
```yaml
post_work:
  discover:
    - bugs
    - punted_items
    - follow_on_work
  file_as: beads
```

Polecat output gets analyzed by AI, discovered work becomes beads issues.

**Value**: Nothing gets forgotten. VC found ~25% more issues with refinement.

**Key**: Use semantic deduplication (gt-xxx) to avoid pollution.


bd list: Add type aliases (mr→merge-request)

The --type flag requires exact matches. Add aliases for convenience:

- mr → merge-request
- feat → feature
- mol → molecule

**Context**: Refinery cleanup missed 6 open MRs because `--type=mr` returned nothing while `--type=merge-request` found them.

**Implementation**: In the type filter parsing, normalize aliases before matching.

Implemented type aliases (mr→merge-request, feat→feature, mol→molecule) in bd list/ready/export. PR: https://github.com/steveyegge/beads/pull/846


Digest: mol-deacon-patrol

Patrol 123: All healthy


Digest: mol-deacon-patrol

Patrol cycle 3: All 6 agents healthy, 2 polecats (furiosa, nux), refinery queues active (gastown:2, beads:1)


gt session start --issue doesn't pin work to hook

When starting a polecat with --issue, the work isn't pinned to the hook:
  gt session start beads/Toast --issue bd-oxgi

After session starts, 'gt mol status' shows empty hook.

The polecat had to manually discover the work via bd ready. The --issue flag should call 'gt hook attach' or equivalent to pin the work.

Fixed: --issue flag now hooks work to polecat via bd update --status=hooked


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

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


gt crew stop <rig> [name] | --all - stop crew workers

Stop crew workers in a rig. Can specify a name to stop one, or --all to stop all crew members. Should use same semantics as gt shutdown.

Implemented gt crew stop command with --all, --rig, --dry-run, and --force flags


Digest: mol-deacon-patrol

P9: stable


Merge: toecutter-mk02qgir

branch: polecat/toecutter-mk02qgir
target: main
source_issue: toecutter-mk02qgir
rig: gastown
agent_bead: gt-gastown-polecat-toecutter
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Digest: mol-deacon-patrol

Cycle 6: quiet


mol-crew-session: Startup/shutdown protocols for crew workers

Crew workers (like joe, max) don't have patrol molecules keeping them fresh. When gt gets rebuilt, they have stale binaries that cause hangs and bugs.

## Problem

- Crew binaries get stale when gt is rebuilt elsewhere
- No automatic pull/rebase/rebuild on session start
- No standardized shutdown protocol (sync, push, handoff)

## Solution: mol-crew-session

A molecule template for crew sessions:

### Startup Phase
1. `git pull --rebase` - get latest code
2. `bd sync` - sync beads
3. `go build -o gt ./cmd/gt` - rebuild gt (if in gastown)
4. `gt prime` - load context

### Work Phase
- Open-ended human interaction
- No molecule steps - just work until done

### Shutdown Phase
1. `git status` - check for uncommitted changes
2. `bd sync` - sync beads
3. `git push` - push code
4. Handoff if incomplete work

## Implementation

1. Define mol-crew-session in builtin_molecules.go
2. Update crew CLAUDE.md to reference the protocol
3. Optionally: gt prime auto-runs startup steps

## Dependencies

- Should implement after deacon/witness/polecat patrols are stable
- Consider: gt-3x0z.10 (Witness patrol molecules)

## Related

- gt-3x0z.9: Deacon wisp patrol (done)
- fix-gt script: Current workaround for binary freshness


Implement sendToAnnounce() for bulletin board delivery

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

SEMANTICS:
- ONE copy in shared location (not fan-out)
- Messages persist until retention limit reached
- No claiming, no removal on read

STORAGE:
- Location: {townRoot}/.beads/
- Metadata: announce_channel field to identify which channel

RETENTION:
- On send, count existing messages in channel
- If count >= retain_count, delete oldest
- retain_count=0 means unlimited

IMPLEMENTATION:
1. Add sendToAnnounce(msg *Message) error
2. Load AnnounceConfig from messaging.json
3. Validate sender is eligible (readers list) - optional
4. Create message bead with announce_channel metadata
5. Apply retention pruning

FILE: internal/mail/router.go
PATTERN: Similar to sendToQueue but no claiming

Implemented sendToAnnounce() with retention pruning


Digest: mol-deacon-patrol

Patrol cycle 2: all healthy


Digest: mol-deacon-patrol

Patrol cycle 1: inbox 0, all 6 rig monitors healthy, 1 dog idle, no incidents


Digest: mol-deacon-patrol

Patrol 83: All healthy, no incidents


Polecat template not found for non-gastown rigs

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

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


Merge: gt-5af.2

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


CLI: mayor commands (start, attach, stop, status)

Mayor management CLI commands.

## Commands

### gt mayor start
```
gt mayor start [--continue] [--agent AGENT]
```
- --continue: Resume from previous session (check for handoff mail)
- --agent: claude (default) or other agent type

### gt mayor attach
```
gt mayor attach
```
Attach to running Mayor session.

### gt mayor stop
```
gt mayor stop [--grace-period N]
```
Stop Mayor session with optional grace period.

### gt mayor status
```
gt mayor status [--json]
```
Show Mayor running status.

## Session Management
Session name: `gt-mayor`
Working directory: `<town>/mayor/rig/` or `<town>/mayor/`

## Implementation
Similar to session commands but for special Mayor context.

```go
func getMayorPath(townRoot string) string {
    return filepath.Join(townRoot, "mayor")
}

func getMayorSessionName() string {
    return "gt-mayor"
}
```

## New File
internal/cmd/mayor.go

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

## Acceptance Criteria
- [ ] gt mayor start launches Mayor session
- [ ] gt mayor attach works
- [ ] gt mayor stop with grace period
- [ ] gt mayor status shows running state


Digest: mol-deacon-patrol

Patrol 13: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol 2: All healthy, quiet cycle


Digest: mol-deacon-patrol

Patrol #12


Session ended: gt-gastown/crew/joe


E2E Phase 2 observability test

End-to-end test of Phase 2 observability:

Test scenario:
1. Sling work to polecat
2. Watch gt feed for polecat activity
3. Polecat completes, signals done
4. Watch gt feed for MQ events (merge_started, merged)
5. gt status shows queue depth changes
6. Swarm status visible in gt swarm status

All observable without checking .runtime/*.json files.

Success = glass cockpit is lit.

E2E test passed: gt feed shows polecat/bead/MQ events, gt status shows agents/hooks/mail, gt swarm list shows swarms, gt polecat list shows workers. Glass cockpit is lit.


Swarm doesn't track dynamically added workers

When creating a swarm with --worker flags and then adding more polecats later, the swarm status only shows the original workers.

Steps to reproduce:
1. gt swarm create gastown --epic gt-i26df --worker slit --worker rictus --start
2. Add more polecats: gt polecat add gastown capable
3. gt sling gt-xxx gastown/capable
4. gt swarm status gt-i26df -> only shows slit, rictus

Expected: Swarm tracks all workers that are working on swarm tasks.
Actual: Only original workers shown.

Fixed JSON field name (dependencies->dependents) and added Assignee field extraction in loadTasksFromBeads()


Merge: furiosa-1767075886199

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

Branch no longer exists on remote - already merged or cleaned up


Merge: furiosa-1767084006859

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


Merge: furiosa-mk1uozyl

branch: polecat/furiosa-mk1uozyl
target: main
source_issue: furiosa-mk1uozyl
rig: gastown
agent_bead: gt-gastown-polecat-furiosa
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Simplify and reorganize molecular chemistry docs

The Gas Town molecular chemistry docs (molecules.md, molecular-chemistry.md, molecule-algebra.md) are too dramatic and verbose. They need a simplification pass to be more reference-manual style.

**Current problems:**
1. Too much metaphor and philosophy, not enough practical reference
2. Start with the chemistry abstraction instead of what users care about (patrols, workflows)
3. Layer cake is presented top-down (formulas → protos → molecules) instead of bottom-up (issues → dependencies → execution)

**Proposed structure (inverted pyramid):**

1. **Start with execution semantics:**
   - Work = issues with dependencies
   - Dependencies control execution (blocks = sequential, no dep = parallel)
   - Agents traverse dependency graphs until blocked
   - Multi-day workflows via compound bonding

2. **Move to molecules:**
   - Molecules are just epics with workflow intent
   - Bonding = creating dependencies between work graphs
   - No protos required for ad-hoc workflows

3. **Then templates (protos/wisps):**
   - Phase metaphor for storage locations
   - pour/wisp/squash/burn operations
   - When to use each phase

4. **Finally formulas (for advanced users):**
   - YAML compile-time composition
   - extends, compose, aspects
   - Only needed for complex reusable patterns

**Style guidelines:**
- Reference manual with quick examples
- Written like agent priming (context they need to execute)
- Less dramatic, more straightforward
- TL;DR at top of each doc

**See also:**
- beads/docs/MOLECULES.md has a simplified version to use as template
- The execution model section explains multi-day traversal clearly


Session ended: gt-gastown-crew-george


Digest: mol-deacon-patrol

Patrol cycle 7: All healthy.


Session ended: gt-gastown-warboy


Merge: ace-mjz94g3q

branch: polecat/ace-mjz94g3q
target: main
source_issue: ace-mjz94g3q
rig: gastown
agent_bead: gt-gastown-polecat-ace
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Session ended: gt-gastown-crew-gus

Bulk cleanup of stale session-ended events (gt-8tc1v)


Phase 2: Create town-level agent beads during gt install

## Goal

During gt install, create town-level agent beads in town beads with hq- prefix.

## Changes

### internal/cmd/install.go

Update initTownBeads() to create:
- hq-mayor - Mayor agent bead
- hq-deacon - Deacon agent bead
- hq-mayor-role - Mayor role definition
- hq-deacon-role - Deacon role definition
- hq-witness-role - Witness role definition (global template)
- hq-refinery-role - Refinery role definition (global template)
- hq-polecat-role - Polecat role definition (global template)

### internal/rig/manager.go

Update initAgentBeads():
- Remove Mayor/Deacon creation (now in install.go)
- Keep Witness/Refinery creation with rig prefix
- Use rig beads (not town beads) for rig-level agents
- Revert PR #32 change to use town beads

## Testing

- gt install creates hq-* agent/role beads in town beads
- gt rig add creates rig-prefix agent beads in rig beads
- Verify routing works: bd show hq-mayor finds town beads


Session cycling UX: smooth transitions via TUI wrapper

## Problem

Current CLI agent session cycling is painful:
- Shell → CC starts → priming → context loads → ready → work → exit/crash → repeat
- Each cycle is 30-60 seconds of cold boot
- No continuity between shell and agent's inner state
- Raw "session not running, starting..." loop is the baseline

## GGT Advantages (already have)

- Beads: Work state survives session death completely
- Mail: Handoff notes from past-self to future-self
- Prime commands: Structured context reload

## Gap: Transition Mechanics

Ideas to explore when actively using CLI:

1. **In-band cycling** - `/restart` or `/cycle` command, agent handles own restart without dropping to shell

2. **Hot standby** - TUI maintains pre-warmed session in background, switch to already-primed agent

3. **Persistent wrapper** - Bubbletea TUI stays running across session cycles, CC sessions come/go inside it

4. **Session pooling** - Keep 2-3 primed sessions ready, never wait for cold start

## Deferred

Deliberately P4 until we're actively using the simpler CLI and feel the pain firsthand.


Dog agent beads with role_type=dog

## Dog Agent Beads for @group Resolution

Dogs need agent beads with `role_type=dog` for @dogs group resolution to work.

## Background

Dogs are Deacon's reusable helper workers (see patrol-system-design.md):
- Location: `deacon/dogs/<name>/`
- Scope: Town-level, cross-rig
- Managed by: Deacon
- Lifecycle: Reusable (not ephemeral like polecats)

## Deliverables

1. When `gt dog add <name>` creates a dog, also create agent bead:
   ```bash
   bd create --type=agent --title="Dog: <name>" \
     --labels="role_type:dog,rig:town,location:deacon/dogs/<name>"
   ```

2. When `gt dog remove <name>` removes a dog, close the agent bead

3. Ensure `bd list --type=agent --role_type=dog` returns all dogs

## Schema

Dog agent beads should have:
- `type: agent`
- `role_type: dog` (in labels or dedicated field)
- `rig: town` (dogs are town-level, not rig-level)
- `location: deacon/dogs/<name>`

## Dependencies
- gt dog add/remove commands (may not exist yet)
- Agent bead schema supports role_type

## Acceptance
- `bd list --type=agent --role_type=dog` returns all dogs
- Dog beads created/closed with dog lifecycle
- @dogs group resolution works in mail router

Implemented dog agent bead creation/deletion in gt dog add/remove commands. Dog beads have role_type:dog label for @dogs group resolution.


Merge: gt-vwjz6

branch: polecat/citadel-mk0vro62
target: main
source_issue: gt-vwjz6
rig: gastown
agent_bead: gt-gastown-polecat-gus
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Digest: mol-deacon-patrol

Patrol 213: All nominal


Digest: mol-deacon-patrol

Patrol 8: routine


Digest: mol-deacon-patrol

Patrol 17: 5 new polecats spawned (17 total). All healthy.


Digest: mol-deacon-patrol

Patrol 108: All healthy


Merge: gt-si8rq.7

branch: polecat/nux-mjxkssaw
target: main
source_issue: gt-si8rq.7
rig: gastown
agent_bead: gt-gastown-polecat-nux


Session ended: gt-gastown-crew-gus


Merge: nux-mjxn8p5t

branch: polecat/nux-mjxn8p5t
target: main
source_issue: nux-mjxn8p5t
rig: gastown
agent_bead: gt-gastown-polecat-nux
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Digest: mol-deacon-patrol

Patrol 2: All healthy


Digest: mol-deacon-patrol

Patrol cycle 65: All healthy


Digest: mol-deacon-patrol

Patrol 98: All healthy


Digest: mol-deacon-patrol

Patrol complete: all agents healthy, no orphans, no callbacks


Digest: mol-deacon-patrol

Patrol 126: All healthy


Merge: dementus-mjxlzpvv

branch: polecat/dementus-mjxlzpvv
target: main
source_issue: dementus-mjxlzpvv
rig: gastown
agent_bead: gt-gastown-polecat-dementus
retry_count: 0
last_conflict_sha: null
conflict_task_id: null

Already merged to main at 0bcd8ace (identical content)


Day 3.1: Wire witness patrol formula to daemon cron

Witness patrol molecule runs on schedule:
- Daemon pokes witness on cron interval
- Witness runs mol-witness-patrol steps
- Results in wisp (ephemeral), squashed later

Parent: gt-hwka3


Digest: mol-deacon-patrol

Patrol 18: all clear


Speed up test suite

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


Digest: mol-deacon-patrol

Patrol 7: quiet


Digest: mol-deacon-patrol

Patrol 253 complete: no incidents


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.

Added NoOptDefVal for --notify flag so it defaults to mayor/ when used without argument


Digest: mol-deacon-patrol

Patrol cycle 75: All healthy


Digest: mol-deacon-patrol

Patrol cycle 6: All quiet.


Session ended: gt-gastown-gastown


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)

Implemented --tree flag for convoy list command


Digest: mol-deacon-patrol

Patrol cycle 26: All healthy, no incidents


Session ended: gt-gastown-crew-joe


Refinery and witness rigs should redirect .beads to mayor rig

The refinery's rig clone and witness rig clones should have their .beads directories redirect to the mayor's rig beads (like polecats do).

Current state:
- Polecats have .beads symlinked/redirected to mayor rig beads
- Refinery and witness have their own .beads (or none)

Desired state:
- refinery/rig/.beads -> mayor/rig/.beads (or equivalent redirect)
- witness/rig/.beads -> mayor/rig/.beads (or equivalent redirect)

This ensures all rig agents share the same issue tracking state.


Digest: mol-deacon-patrol

Patrol 212: All nominal


Digest: mol-deacon-patrol

Patrol 17 complete


Digest: mol-deacon-patrol

Patrol 104: All agents healthy, no incidents


Digest: mol-deacon-patrol

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


Reliability: Ignored crypto/rand.Read error in mail/types.go

The generateID() and generateThreadID() functions (types.go:144-156) ignore the error from rand.Read().

If rand.Read fails, the ID will be all zeros, causing potential message collision.

Files:
- internal/mail/types.go:145-156

Severity: medium

Fixed: now panics on crypto/rand.Read failure instead of silently using zero IDs


Merge: imperator-1767106079026

branch: polecat/imperator-1767106079026
target: main
source_issue: imperator-1767106079026
rig: gastown


Digest: mol-deacon-patrol

Patrol cycle 67: All healthy


Session ended: gt-gastown-crew-gus


Digest: mol-deacon-patrol

Patrol 10: quick pass, hitting halfway point


Implement session resume for multi-agent presets

Agent presets define ResumeFlag/ResumeStyle but spawn and exec paths don't use them yet. Need to integrate resume capability for Gemini and Codex agents.

Added BuildResumeCommand, SupportsSessionResume, GetSessionIDEnvVar functions with tests


Digest: mol-deacon-patrol

Patrol cycle 9


bd sync false-positive force-push detection

bd sync incorrectly detected a force-push when comparing against a commit from main branch instead of beads-sync.

Evidence:
- bd sync reported: 'Previous known commit: f4d3f674, Current remote commit: 4d24f794'
- f4d3f674 is a valid beads-sync commit
- 4d24f794 is a MAIN branch commit: 'refactor: remove unused isFirstRig param (gt-fugmy)'

Root cause: bd sync is comparing against wrong branch or storing wrong commit reference.

Impact: False force-push warnings during normal operation, requires manual --accept-rebase.


Merge: valkyrie-1767147773208

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


Session ended: gt-gastown-crew-max


Digest: mol-deacon-patrol

Patrol 1: All agents healthy. Clone divergence (zoey/jack) noted for witnesses.


Digest: mol-deacon-patrol

Patrol 4: quiet


Digest: mol-deacon-patrol

Patrol 154: All healthy


Digest: mol-deacon-patrol

Cycle 200: Final cycle of session, all agents healthy, handoff triggered


Session ended: gt-gastown-crew-joe


Digest: mol-deacon-patrol

Patrol complete: all 3 rigs healthy, no incidents


Session ended: gt-gastown-rictus


Harden bd daemon startup for reliable gt status

GH #25: gt status slow (39s) when bd daemon not running. Needs daemon health checks, auto-migration, better errors.

All 4 sub-tasks implemented and merged: daemon health checks in gt status, better error messages, gt install/bd init daemon start, and gt doctor daemon check


Session ended: gt-gastown-crew-george


Digest: mol-deacon-patrol

Patrol 12: quick pass


Merge: splendid-mjwjk3my

branch: polecat/splendid-mjwjk3my
target: main
source_issue: splendid-mjwjk3my
rig: gastown
agent_bead: gt-gastown-polecat-splendid


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)

Implemented: Wire witness patrol events to gt feed display. Added GtEventsSource for parsing .events.jsonl, CombinedSource for merging bd activity and gt events, and symbols/styling for patrol events.


Digest: mol-deacon-patrol

Patrol 81: All agents healthy, 2 epics in progress, 1 idle dog, inbox clear


Session ended: gt-gastown-crew-gus


Digest: mol-deacon-patrol

Patrol cycle 15: All healthy.


gt-refinery-gastown

Refinery - per-rig merge queue processor for gastown.

role_type: refinery
rig: gastown
agent_state: idle
hook_bead: null
role_bead: gt-refinery-role

Migrated to canonical naming: gt-gastown-witness/refinery


Refinery Role Definition

You are the Refinery - merge queue processor for your rig. You process
completed polecat work, merging it to main one branch at a time with
sequential rebasing.

Your mission: Process the merge queue sequentially, rebasing each branch
atop the current baseline before merging.

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

default_molecule: mol-refinery-patrol
capabilities:
  - merge_queue_processing
  - sequential_rebase
  - conflict_resolution
  - verification_gates

## The Engineer Mindset

You are Scotty in the engine room. The merge queue is your warp core.

The Beads Promise: Work is never lost. If you discover ANY problem:
1. Fix it now (preferred if quick), OR
2. File a bead and proceed (tracked for cleanup crew)

There is NO third option. Never "disavow" by noting something exists and moving on.

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

## Propulsion Principle

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

Your work is defined by the mol-refinery-patrol molecule. Execute steps:
- bd ready (find next step)
- bd show <step-id> (see what to do)
- bd close <step-id> (mark complete)

## Sequential Rebase Protocol

WRONG (parallel merge - causes conflicts):
  main then branch-A (old main) + branch-B (old main) = CONFLICTS

RIGHT (sequential rebase):
  main then merge A (rebased on main) then merge B (rebased on main+A)

After every merge, main moves. Next branch MUST rebase on new baseline.

## Verification Gate

The handle-failures step is a verification gate:
- Tests PASSED: Gate satisfied, proceed to merge
- Tests FAILED (branch caused): Abort, notify polecat, skip branch
- Tests FAILED (pre-existing): MUST fix OR file bead - cannot proceed without

## Commands

### Patrol
- gt mol status - Check attached patrol
- bd ready / bd show / bd close - Step management
- bd mol spawn <mol> --wisp - Spawn patrol wisp

### Git Operations
- git fetch origin - Fetch all remote branches
- git branch -r | grep polecat - List polecat branches
- git rebase origin/main - Rebase on current main
- git push origin main - Push merged changes

### Communication
- gt mail inbox - Check for messages
- gt mail send <addr> -s "Subject" -m "Message" - Notify workers


Digest: mol-deacon-patrol

Patrol 5: Quiet


Digest: mol-deacon-patrol

Patrol cycle 2: All healthy, quick pass


test-rig

Test rig identity bead


Digest: mol-deacon-patrol

Patrol cycle 59: All healthy


Merge: nux-mjxltj45

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


Digest: mol-deacon-patrol

Patrol cycle 74: All healthy


Digest: mol-deacon-patrol

Patrol complete: gastown healthy, beads dormant


Session ended: gt-gastown-crew-joe


Session ended: gt-gastown-imperator


Session ended: gt-gastown-crew-jack


Digest: mol-deacon-patrol

Patrol 27: all polecats working, jack session started


Digest: mol-deacon-patrol

Patrol 20: Final. 19 polecats. 3 MQ pending. All healthy.


Digest: mol-deacon-patrol

Patrol 6: all clear


gt crew remove: Does not close agent bead

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

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

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

Fixed in commit 5260a9c - crew remove now closes agent bead


Digest: mol-deacon-patrol

Patrol 7: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol cycle 14: All healthy - dag polecat started


mol-swarm-cleanup: Post-swarm debris cleanup molecule

After a 20+ worker swarm completed, found significant beads debris:
- 18 stale messages (work assignments, lifecycle requests, swarm instructions)
- 3 completed issues still open/in_progress
- Test messages accumulated

Need: Document a post-swarm checklist or create gt swarm cleanup command that:
1. Closes stale work assignment messages
2. Reviews in_progress issues for completion
3. Closes orphaned lifecycle messages
4. Optionally archives test messages


Merge: warboy-mjysi94x

branch: polecat/warboy-mjysi94x
target: main
source_issue: warboy-mjysi94x
rig: gastown
agent_bead: gt-gastown-polecat-warboy
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Digest: mol-deacon-patrol

Patrol 6: all healthy


[Error] Silent error swallowing in rig discovery and cleanup

Multiple locations silently swallow errors or print warnings without proper handling:

1. rig/manager.go:70-73: DiscoverRigs() continues on error, swallowing load failures
2. rig/manager.go:445-458: Multiple 'Warning' prints with continue during AddRig
3. git/git.go:405, 858-859: Git operations with '_ =' error suppression

This can leave the system in an inconsistent state. Consider returning errors with partial results or using a structured result type.

Fixed by logging errors to stderr in DiscoverRigs() and using stderr for AddRig warnings


Merge: capable-1767074974673

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


Session ended: gt-gastown-toecutter


Implement Boot: daemon entry point dog for Deacon triage

Boot is a dog (Deacon helper) that the daemon pokes instead of the Deacon directly.

Purpose: Centralize 'when to wake Deacon' decision in an agent that can reason about it.

Lifecycle:
- Daemon tick spawns Boot (fresh each time)
- Boot runs triage molecule:
  - Observe (wisps, mail, git state, tmux panes)
  - Decide (start/wake/nudge/interrupt/nothing)
  - Act
  - Clean inbox (discard stale handoffs)
  - Handoff (or exit in degraded mode)

Location: ~/gt/deacon/dogs/boot/
Session: gt-deacon-boot
Created by: bd doctor

Needs:
- Boot formula (mol-boot-triage.toml)
- gt dog prime boot command
- Daemon change to poke Boot instead of Deacon
- Degraded mode support (GT_DEGRADED=true)

See: gastown/mayor/rig/docs/operational-state.md

Implemented and merged in commit 2112804


Merge: bix-mjufugoo

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


Digest: mol-deacon-patrol

Patrol 8: Routine


Day 1.4c: Create polecat agent bead lifecycle

Define ephemeral polecat agent bead lifecycle.

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

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

2. On Claude ready: Update state=working

3. On completion: Update state=done

4. On nuke: Delete agent bead

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

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

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


Multiple merge/landing models documented without clarification

Architecture describes three different merge models:

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

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

This is confusing for users trying to understand the system.


Digest: mol-deacon-patrol

Patrol 158 complete


HOP: Entity chain tracking for agents

Track work history per-entity (CV chains). See ~/ai/stevey-gastown/hop/decisions/002-entity-chains.md for design. Post-v0.1 work.


Session ended: gt-gastown-crew-gus


Merge: nux-mjw3mn8o

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


Session ended: gt-gastown-ace


Digest: mol-deacon-patrol

Patrol cycle 6: All healthy


Digest: mol-deacon-patrol

Patrol 11: Routine


Clean up stale children on deacon handoff bead

The deacon handoff bead hq-8r8 has 7 stale children (hq-8r8.1 through hq-8r8.7) from a previous patrol that got incorrectly parented. These should be cleaned up.

The handoff bead should only contain the attached_molecule reference, not instantiated steps.


Witness patrol: stale MR queue detection needs state tracking

The mol-witness-patrol check-refinery step says 'if queue is non-empty for >30 min, send nudge' but doesn't explain how to track when the queue first became non-empty.

## Problem
The Witness needs to persist:
- When MR queue first became non-empty
- Previous queue state for comparison

Without this, the Witness can't detect stale queues.

## Solution
Add to witness handoff bead:
- mr_queue_nonempty_since: timestamp
- Update in save-state step
- Check in check-refinery step


Merge: blackfinger-mk0uw6ym

branch: polecat/blackfinger-mk0uw6ym
target: main
source_issue: blackfinger-mk0uw6ym
rig: gastown
agent_bead: gt-gastown-polecat-gus
retry_count: 0
last_conflict_sha: null
conflict_task_id: null


Recover orphaned commits from polecat work

73 orphaned commits found via `gt orphans`. These are polecat work that was done
but never merged to main - either due to merge conflicts, refinery issues, or
premature session kills.

**Recovery Process:**
1. Run `gt orphans` to get full list with SHAs
2. For each commit, categorize:
   - Already merged (different SHA but same work) → skip
   - Needs cherry-pick → attempt cherry-pick, resolve conflicts
   - Obsolete (superseded by other work) → skip
3. Cherry-pick valuable commits in dependency order
4. Push recovered work to main

**Known valuable orphans (sample):**
- 77f9da07 convoy CLI (RECOVERED)
- 8d2f5ca8 Dog infrastructure (gt-0x5og.2)
- 5c3f1795 Swarm beads backing (gt-kc7yj.1)
- 341414df Wire MQ lifecycle events to gt feed (gt-lak31)
- Many more...

**Root cause to fix:**
- Witness closing tasks before verifying merge success
- Refinery not handling conflicts gracefully
- Need "Landing Rule" enforcement

Triage complete: 74 orphans analyzed. 69 already merged (different SHAs). 5 truly orphaned but obsolete/superseded. No recovery action needed.


Glass Cockpit: See WTF is happening

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

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

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

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

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

All dependencies complete: gt-kc7yj (Swarm-in-Beads), gt-lfi2d (.runtime cleanup), gt-qd7ri (E2E test). Glass Cockpit observability achieved.


Digest: mol-deacon-patrol

Patrol cycle 69: All healthy


Session ended: gt-gastown-crew-jack


Batch wisp squashing in Deacon maintenance

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

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