docs/concepts/polecat-lifecycle.md
Understanding the three-layer architecture of polecat workers
Polecats have three distinct lifecycle layers that operate independently. The key design principle: polecats are persistent. They survive work completion and can be reused across assignments.
Polecats have four operating states:
| State | Description | How it happens |
|---|---|---|
| Working | Actively doing assigned work | Normal operation after gt sling |
| Idle | Work completed, sandbox preserved for reuse | After gt done completes successfully |
| Stalled | Session stopped mid-work | Interrupted, crashed, or timed out without being nudged |
| Zombie | Completed work but failed to exit | gt done failed during cleanup |
State cycle (happy path):
┌──────────┐
┌───>│ IDLE │<──── sync sandbox to main, clear hook
│ └────┬─────┘
│ │ gt sling
│ v
│ ┌──────────┐
│ │ WORKING │<──── session active, hook set
│ └────┬─────┘
│ │ gt done
│ v
│ ┌──────────┐
└────┤ IDLE │──── push branch, submit MR, go idle
└──────────┘
No nuke in the happy path. Polecats cycle: IDLE -> WORKING -> IDLE.
Key distinctions:
gt sling.Polecats persist after completing work. When a polecat finishes its assignment:
gt doneThe next gt sling reuses idle polecats before allocating new ones, avoiding
the overhead of creating fresh worktrees.
The Refinery owns the merge queue. Once gt done submits work:
Early designs treated polecats as monolithic. This caused recurring issues:
| Concept | Lifecycle | Old behavior |
|---|---|---|
| Identity | Long-lived (name, CV, ledger) | Destroyed on nuke |
| Sandbox | Per-assignment (worktree, branch) | Destroyed on nuke |
| Session | Ephemeral (Claude context window) | = polecat lifetime |
Separating these three layers means idle polecats are a healthy state (not waste), eliminates unnecessary worktree creation overhead, and preserves capability records (CV, completion history) across assignments.
| Layer | Component | Lifecycle | Persistence |
|---|---|---|---|
| Identity | Agent bead, CV chain, work history | Permanent | Never dies |
| Sandbox | Git worktree, branch | Persistent across assignments | Created on first sling, reused thereafter |
| Session | Claude (tmux pane), context window | Ephemeral per step | Cycles per step/handoff |
The polecat's identity is permanent. It includes:
Identity survives all session cycles and sandbox resets. In the HOP model, this IS the polecat — everything else is infrastructure that comes and goes. See Polecat Identity below for details.
The Claude session is ephemeral. It cycles frequently:
gt handoff)Key insight: Session cycling is normal operation, not failure. The polecat continues working—only the Claude context refreshes.
Session 1: Steps 1-2 → handoff
Session 2: Steps 3-4 → handoff
Session 3: Step 5 → gt done
All three sessions are the same polecat. The sandbox persists throughout.
The sandbox is the git worktree—the polecat's working directory:
~/gt/gastown/polecats/Toast/
This worktree:
gt sling and persists across assignmentsgt slingThe Witness never destroys sandboxes. Only explicit gt polecat nuke removes them.
When work completes and the polecat goes idle, the sandbox is synced to main:
# In the polecat's worktree (done automatically by gt done / gt sling)
git checkout main
git pull origin main
git branch -D polecat/<name>/<old-issue>@<timestamp>
# Worktree is now clean, on main, ready for next assignment
When new work is slung:
# Create fresh branch from current main
git checkout -b polecat/<name>/<new-issue>@<timestamp>
# Start working
No worktree add/remove between assignments. Just branch operations on an existing worktree. This avoids the ~5s overhead of creating fresh worktrees.
The slot is the name allocation from the polecat pool:
# Pool: [Toast, Shadow, Copper, Ash, Storm...]
# Toast is allocated to work gt-abc
The slot:
polecats/Toast/)gt-gastown-Toast)gastown/polecats/Toast)┌─────────────────────────────────────────────────────────────┐
│ gt sling │
│ → Find idle polecat OR allocate slot from pool (Toast) │
│ → Create/repair sandbox (worktree on new branch) │
│ → Start session (Claude in tmux) │
│ → Hook molecule to polecat │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Work Happens │
│ │
│ Session cycles happen here: │
│ - gt handoff between steps │
│ - Compaction triggers respawn │
│ - Crash → Witness respawns │
│ │
│ Sandbox persists through ALL session cycles │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ gt done (persistent model) │
│ → Push branch to origin │
│ → Submit work to merge queue (MR bead) │
│ → Set agent state to "idle" │
│ → Kill session │
│ │
│ Work now lives in MQ. Polecat is IDLE, not gone. │
│ Sandbox preserved for reuse by next gt sling. │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Refinery: merge queue │
│ → Rebase and merge to target branch │
│ (main or integration branch — see below) │
│ → Close the issue │
│ → If conflict: create task for available polecat │
│ │
│ Integration branch path: │
│ → MRs from epic children merge to integration/<epic> │
│ → When all children closed: land to main as one commit │
└─────────────────────────────────────────────────────────────┘
Session cycling: Normal. Claude restarts, sandbox stays, slot stays.
gt handoff # Session cycles, polecat continues
Sandbox repair: On reuse. gt sling resets the worktree to a fresh branch.
gt sling gt-xyz gastown # Reuses idle Toast, repairs worktree
Session cycling happens constantly. Sandbox repair happens between assignments.
Anti-pattern:
gt polecat done Toast # DON'T: external state manipulation
gt polecat reset Toast # DON'T: manual lifecycle control
Correct:
# Polecat signals its own completion:
gt done # (from inside the polecat session)
# Only explicit nuke destroys polecats:
gt polecat nuke Toast # (destroys sandbox, identity persists)
Polecats manage their own session lifecycle. External manipulation bypasses verification.
An idle polecat has no hook and no session — this is normal. It completed
its work and is waiting for the next gt sling.
A stalled polecat has a hook but no session — this is a failure:
Recovery for stalled:
# Witness respawns the session in the existing sandbox
# Or, if unrecoverable:
gt polecat nuke Toast # Clean up the stalled polecat
gt sling gt-abc gastown # Respawn with fresh polecat
Anti-pattern: Thinking session restart = losing work.
# Session ends (handoff, crash, compaction)
# Work is NOT lost because:
# - Git commits persist in sandbox
# - Staged changes persist in sandbox
# - Molecule state persists in beads
# - Hook persists across sessions
The new session picks up where the old one left off via gt prime.
Sessions cycle for these reasons:
| Trigger | Action | Result |
|---|---|---|
gt handoff | Voluntary | Clean cycle to fresh context |
| Context compaction | Automatic | Forced by Claude Code |
| Crash/timeout | Failure | Witness respawns |
gt done | Completion | Session exits, polecat goes idle |
All except gt done result in continued work. Only gt done signals completion
and transitions the polecat to idle.
The Witness monitors polecats but does NOT:
The Witness DOES:
gt done failed)Key insight: Polecat identity is permanent; sessions are ephemeral, sandboxes are persistent.
In the HOP model, every entity has a chain (CV) that tracks:
The polecat name (Toast, Shadow, etc.) is a slot from a pool — persistent until explicit nuke. The agent identity that executes as that polecat accumulates a work history across all assignments.
POLECAT IDENTITY (permanent) SESSION (ephemeral) SANDBOX (persistent)
├── CV chain ├── Claude instance ├── Git worktree
├── Work history ├── Context window ├── Branch
├── Skills demonstrated └── Dies on handoff └── Repaired on reuse
└── Credit for work or gt done by gt sling
This distinction matters for:
As of 2026-03-07 (gt-o8g8 audit), all core lifecycle operations are shipped and running in production. See design/polecat-lifecycle-patrol.md § 10 for the full implementation matrix and design/persistent-polecat-pool.md for phase-by-phase shipping status.
Key files:
internal/cmd/done.go — work submission, sandbox sync, idle transitioninternal/cmd/sling.go + polecat_spawn.go — idle reuse, branch-only repairinternal/cmd/handoff.go — session cycling for all rolesinternal/witness/handlers.go — cleanup pipeline, POLECAT_DONE routing, zombie/orphan detectioninternal/polecat/manager.go — stale detection, idle reuse (FindIdlePolecat, ReuseIdlePolecat), pool management