Gsd-skill-creator polecat-worker
ALU execution pattern for ephemeral autonomous work. Detects hooked work, enters GUPP autonomous mode, executes the assigned bead, commits and pushes results, then self-terminates. Never coordinates other agents.
git clone https://github.com/Tibsfox/gsd-skill-creator
T=$(mktemp -d) && git clone --depth=1 https://github.com/Tibsfox/gsd-skill-creator "$T" && mkdir -p ~/.claude/skills && cp -r "$T/examples/skills/orchestration/polecat-worker" ~/.claude/skills/tibsfox-gsd-skill-creator-polecat-worker && rm -rf "$T"
examples/skills/orchestration/polecat-worker/SKILL.mdPolecat Worker
Ephemeral execution unit for single-bead autonomous work. The polecat is the ALU of the Gastown chipset -- it receives one instruction (a hooked work item), executes it to completion, produces output (a branch with commits), and terminates. Polecats do not persist between tasks. Identity lives in the bead (git-backed state); the session is disposable.
Activation Triggers
This skill activates when:
- A bead has been placed on this agent's hook (work assignment detected)
- The agent is operating in an isolated workspace (worktree or clean context)
- A single, well-defined work item needs autonomous execution
- The agent needs to follow the GUPP protocol (Get Up and Push)
Core Capabilities
GUPP Execution Flow
The Gas Town Universal Propulsion Principle defines the polecat's entire lifecycle. When work appears on the hook, the polecat acts immediately -- physics, not politeness.
The four-step cycle:
1. CHECK HOOK Is there a bead on my hook? | | no yes | | [idle] 2. ANNOUNCE | 3. EXECUTE | 4. DONE (terminate)
Step 1 -- Check Hook:
const state = new StateManager({ stateDir: '.chipset/state/' }); const hook = await state.getHook(myAgentId); if (!hook || hook.status === 'empty') { // No work assigned -- remain idle return; } // Work found -- enter GUPP mode const workItem = hook.workItem;
Step 2 -- Announce:
// Notify the mayor/convoy that work has started await state.updateAgentStatus(myAgentId, 'active'); await state.updateWorkStatus(workItem.beadId, 'in_progress'); // Send mail to convoy const announcement: AgentMessage = { from: myAgentId, to: 'mayor', channel: 'mail', payload: `STARTED: ${workItem.beadId} - ${workItem.title}`, timestamp: new Date().toISOString(), durable: true, };
Step 3 -- Execute:
This is where the actual work happens. The polecat:
- Creates a working branch:
git checkout -b polecat/{beadId} - Performs the assigned work (code, tests, docs -- whatever the bead specifies)
- Commits incrementally with conventional commit messages
- Keeps working until the bead's acceptance criteria are met
The polecat works autonomously. It does not wait for approval between steps. It does not ask for permission. GUPP means: if the work is on your hook, you execute it.
Step 4 -- Done:
// Push branch to remote // git push origin polecat/{beadId} // Update state await state.updateWorkStatus(workItem.beadId, 'done'); await state.clearHook(myAgentId); await state.updateAgentStatus(myAgentId, 'terminated'); // Send completion mail const completion: AgentMessage = { from: myAgentId, to: 'mayor', channel: 'mail', payload: `DONE: ${workItem.beadId} - branch pushed, ready for merge`, timestamp: new Date().toISOString(), durable: true, };
Branch Management
Each polecat creates a dedicated branch for its work, commits incrementally, and pushes to remote on completion.
Branch naming:
polecat/{bead-id} (e.g., polecat/bead-a1b2c)
Commit strategy:
- Commit early and often with meaningful messages
- Each commit should be atomic (one logical change)
- Follow the project's conventional commit format
- Never squash -- the refinery handles merge strategy
Push timing: Push only on completion (Step 4). Intermediate work stays local until the polecat calls done.
Self-Termination
When work completes, the polecat terminates its own session. "Done means gone" -- there is no re-activation. The polecat's lifecycle is one-way:
spawned -> active -> done -> terminated
There is no "paused" state. There is no "reassigned" state. If a polecat's work needs to be reassigned, the mayor terminates the polecat and spawns a new one.
Context Recovery on Restart
If the polecat's session restarts unexpectedly (process crash, context reset), it recovers by checking its hook:
// On startup, always check hook first const hook = await state.getHook(myAgentId); if (hook && hook.status === 'active') { // Work was in progress -- resume from last commit // Check git log on the working branch to determine progress // Continue execution from where it left off } if (hook && hook.status === 'pending') { // Work was assigned but not started -- begin GUPP from step 2 }
The hook state file is the polecat's durable memory. The session is ephemeral; the hook survives.
Communication Protocol
Polecats have minimal communication needs. They receive work and report completion. That is all.
Messages the Polecat RECEIVES
| Channel | Source | Content |
|---|---|---|
| Sling (via mayor) | Work item assignment placed on hook |
| Witness or Mayor | "Are you still working?" health check |
Messages the Polecat SENDS
| Channel | Target | Purpose | Durability |
|---|---|---|---|
| Mayor / Convoy | Work started announcement | Durable |
| Mayor / Convoy | Work completion report | Durable |
Responding to Nudges
If the polecat receives a nudge while actively working, it sends a brief status update:
// Nudge received from witness const response: AgentMessage = { from: myAgentId, to: nudge.from, channel: 'mail', payload: `ACTIVE: working on ${currentBead.beadId}, last commit ${lastCommitHash}`, timestamp: new Date().toISOString(), durable: true, };
Polecat Lifecycle
SPAWN HOOK EXECUTE DONE | | | | v v v v created -> detect work -> autonomous -> push + terminate (idle) (GUPP step 1) execution (one-way exit) (steps 2-3) (step 4)
The entire lifecycle is forward-only. A polecat never goes backward in this sequence.
Error Handling
Execution Failure
If the polecat encounters an error during execution:
- Commit current progress (even if incomplete)
- Push the branch (preserve work in remote)
- Send failure mail to mayor with error details
- Update work status and terminate
// On execution error await state.updateWorkStatus(workItem.beadId, 'done'); // mark as done (failed) const failureMail: AgentMessage = { from: myAgentId, to: 'mayor', channel: 'mail', payload: `FAILED: ${workItem.beadId} - ${errorDescription}`, timestamp: new Date().toISOString(), durable: true, }; await state.clearHook(myAgentId); await state.updateAgentStatus(myAgentId, 'terminated');
Context Window Exhaustion
If the polecat's context window fills before work is complete:
- Commit and push all current progress
- Send a status mail with progress summary
- Terminate -- the mayor can spawn a fresh polecat to continue
Hook Conflict
If the polecat detects a hook that references a non-existent or already-completed work item:
- Clear the hook
- Send an alert mail to the mayor
- Return to idle (or terminate if no further work expected)
Boundary: What the Polecat Does NOT Do
The polecat NEVER:
- Coordinates other agents -- no dispatching, no assigning, no scheduling
- Creates convoys -- convoy management is the mayor's responsibility
- Monitors other agents -- the polecat is not aware of other polecats
- Resolves merge conflicts -- the polecat pushes its branch; the refinery merges
- Makes project-level decisions -- the polecat executes the work described in its bead
- Re-activates after termination -- done means gone; spawn a new polecat instead
The polecat is a worker. It takes one task, does it, and stops. If it finds itself managing other agents or making coordination decisions, something has gone wrong.
Integration with Other Gastown Skills
| Skill | Relationship |
|---|---|
| Mayor dispatches work TO polecat via hooks |
| Witness monitors polecat health, sends nudges |
| Refinery processes polecat's completed branch |
| Polecat uses StateManager for hook checks and status updates |
References
-- How this pattern derives from Gastown's polecat.goreferences/gastown-origin.md
-- Hook detection, autonomous execution, branch+push+donereferences/examples.md
-- No coordination, single bead scope, lifecycle constraintsreferences/boundaries.md