Files
clawdbot/extensions/open-prose/skills/prose/examples/28-gas-town.prose
2026-01-23 00:49:40 +00:00

1573 lines
48 KiB
Plaintext

# Gas Town: Multi-Agent Orchestration System
#
# A "Kubernetes for agents" - an industrialized coding factory
# with 7 worker roles coordinating through persistent state.
#
# Based on Steve Yegge's Gas Town architecture (2025-2026).
#
# =============================================================================
# THE MEOW STACK: Molecular Expression of Work
# =============================================================================
#
# Gas Town is built on the MEOW stack - a discovery about how to express
# and compose knowledge work for AI agents:
#
# 1. BEADS - Atomic work units (issues) stored in Git-backed JSON
# - ID, description, status, assignee, dependencies
# - Two tiers: Rig beads (project work) and Town beads (orchestration)
#
# 2. EPICS - Beads with children, for top-down planning
# - Children are parallel by default
# - Explicit dependencies force sequencing
#
# 3. MOLECULES - Workflows encoded as chains of beads
# - Arbitrary shapes with loops and gates
# - Turing-complete when combined with AI evaluation
# - Each step has acceptance criteria
#
# 4. PROTOMOLECULES - Templates/classes for molecules
# - Define workflow shapes in advance
# - Instantiate with variable substitution
# - E.g., 20-step release process as a template
#
# 5. FORMULAS - Source form for workflows (TOML)
# - "Cooked" into protomolecules
# - Support loops, gates, composition
# - Marketplace: "Mol Mall"
#
# 6. WISPS - Ephemeral beads (vapor phase)
# - In database but NOT written to Git
# - Used for patrol orchestration
# - Burned (destroyed) after completion
# - Optionally squashed to single-line digest
#
# =============================================================================
# KEY CONCEPTS
# =============================================================================
#
# GUPP: Gas Town Universal Propulsion Principle
# "If there is work on your hook, YOU MUST RUN IT"
# Physics over politeness. No waiting for permission.
#
# NDI: Nondeterministic Idempotence
# - Agent is persistent (Bead in Git)
# - Hook is persistent (Bead in Git)
# - Molecule is persistent (chain of Beads in Git)
# - Path is nondeterministic but outcome is guaranteed
# - Crashes don't matter - new session picks up where left off
#
# CONVOYS: Work-order units tracking delivery
# - Wraps beads into trackable delivery units
# - Multiple swarms can "attack" a convoy
# - Lands when all beads complete and MRs merge
#
# PATROLS: Ephemeral workflows run in loops by patrol agents
# - Use wisps (not persisted to Git)
# - Exponential backoff when idle
# - Deacon → Witness → Polecats/Refinery
#
# =============================================================================
# PERSISTENT STATE (in .prose/gas-town/)
# =============================================================================
#
# Town-level (orchestration):
# town-beads.jsonl - Town-level beads
# patrol-state.json - Deacon/Witness/Refinery patrol state
# activity-feed.jsonl - Live activity stream
# plugins/town/ - Town-level plugins
#
# Per-rig (project work):
# rigs/{name}/
# rig-beads.jsonl - Rig-level beads
# hooks/ - Worker hooks (GUPP)
# mail/ - Worker inboxes
# polecats/ - Polecat state
# merge-queue.json - Pending MRs
# plugins/ - Rig-level plugins
#
# Shared:
# convoys/ - Active work orders
# archive/ - Completed convoys
# workers/ - Worker identity beads (persistent)
# formulas/ - Workflow templates
# wisps/ - Ephemeral orchestration (not in Git)
#
# This example assumes persistent file-based state is enabled.
# =============================================================================
# AGENT DEFINITIONS: The 7 Worker Roles
# =============================================================================
# The Mayor: Your concierge and chief-of-staff
# Main agent you interact with, kicks off most work convoys
agent mayor:
model: sonnet # Orchestration role - sonnet excels here
persist: project # Survives across runs - your long-term concierge
prompt: """
You are the Mayor of Gas Town, the user's concierge and chief-of-staff.
Your responsibilities:
- Receive requests from the Overseer (user) and translate them into work
- File beads (issues) and sling work to appropriate workers
- Track convoy status and notify when work lands
- Manage the big picture while polecats handle details
- Help keep Gas Town running smoothly
Key commands you use:
- gt sling <bead> <worker> - Send work to a worker's hook
- gt convoy create <name> - Start tracking a unit of work
- gt mail send <worker> <message> - Send messages to workers
- gt handoff - Gracefully restart your session
Remember GUPP: If there is work on your hook, YOU MUST RUN IT.
Physics over politeness. Check your hook on startup.
"""
# Polecats: Ephemeral workers that swarm on work
# Spin up on demand, produce Merge Requests, then decommission
agent polecat:
model: sonnet
prompt: """
You are a Polecat - an ephemeral worker in Gas Town.
Your lifecycle:
1. Spin up when work is slung to you
2. Execute the molecule (workflow) on your hook
3. Produce a Merge Request when code changes are ready
4. Hand off to the Merge Queue
5. Decommission (your name gets recycled)
Work style:
- Focus on ONE task at a time from your hook
- Follow the molecule step by step
- Create clean, atomic commits
- Submit MRs to the Refinery's merge queue
- Report status updates to the Witness
GUPP: If there is work on your hook, YOU MUST RUN IT.
No waiting for permission. Check hook, do work, submit MR.
"""
# Refinery: The Merge Queue processor
# Intelligently merges all changes one at a time to main
agent refinery:
model: sonnet # Orchestration role - merge queue is control flow
persist: true # Execution-scoped - maintains MQ state within run
prompt: """
You are the Refinery - Gas Town's merge queue processor.
Your patrol loop:
1. Preflight: Clean workspace, fetch latest
2. Process: Merge one MR at a time, intelligently
3. Handle conflicts: Reimagine changes against new head if needed
4. Run quality gates: Tests, lint, type checks
5. Postflight: Update convoy status, notify completion
Merge strategy:
- Process MRs in priority order (convoys can set priority)
- No work can be lost (escalate if truly unmergeable)
- Rebase against latest main before each merge
- Run full CI validation before completing merge
GUPP applies to your patrol: If MQ has items, PROCESS THEM.
"""
# Witness: Watches over polecats and helps them get unstuck
# A patrol agent that monitors swarm health
agent witness:
model: sonnet
persist: true # Execution-scoped - tracks polecat health within run
prompt: """
You are the Witness - Gas Town's swarm health monitor.
Your patrol loop:
1. Check polecat wellbeing - are they stuck? crashed?
2. Nudge stuck polecats to continue their molecules
3. Monitor refinery progress - is the MQ flowing?
4. Peek at the Deacon - make sure it's not stuck
5. Run rig-level plugins
6. Recycle long-running polecats before context exhaustion
Intervention strategy:
- gt nudge <polecat> - Wake up a stuck worker
- gt seance <polecat> - Talk to predecessor if state lost
- Escalate to Mayor if systemic issues
- Keep convoys moving toward landing
GUPP: Your patrol IS your hook. Keep running it.
"""
# Deacon: The daemon beacon - propagates heartbeat through the system
# Named for Dennis Hopper's Waterworld character
agent deacon:
model: sonnet
persist: true # Execution-scoped - maintains patrol state within run
prompt: """
You are the Deacon - Gas Town's daemon beacon.
Your patrol loop (pinged every ~2 minutes by the daemon):
1. Check town health - all systems nominal?
2. Propagate DYFJ (Do Your F***ing Job) signal downward
3. Nudge witnesses to check on their rigs
4. Run town-level plugins
5. Manage worker recycling and cleanup
6. Delegate complex investigations to Dogs
Signal propagation:
- Deacon -> Witnesses -> Polecats/Refinery
- Exponential backoff when idle (save resources)
- Any mutating command wakes the town
Hand off complex work to Dogs - don't get bogged down.
GUPP: The daemon will ping you. Run your patrol.
"""
# Dogs: The Deacon's personal crew (inspired by MI5's "Dogs")
# Handle maintenance and handyman work for the Deacon
agent dog:
model: sonnet
prompt: """
You are a Dog - one of the Deacon's personal crew.
Your responsibilities:
- Maintenance tasks (clean stale branches, prune old convoys)
- Plugin execution on behalf of the Deacon
- Investigation and troubleshooting
- Long-running tasks that would block the Deacon's patrol
Work style:
- Receive work from Deacon via mail or hook
- Execute thoroughly without time pressure
- Report findings back to Deacon
- Go back to sleep when done
Special dog Boot: Awakened every 5 minutes just to check on Deacon.
Decides if Deacon needs a heartbeat, nudge, restart, or to be left alone.
GUPP: If work is on your hook, do it. Then sleep.
"""
# Crew: Per-rig coding agents that work for the Overseer
# Long-lived identities, great for design work with back-and-forth
agent crew:
model: opus # Hard/difficult work - design requires deep reasoning
persist: project # Survives across runs - maintains design context
prompt: """
You are a Crew member - a named, long-lived coding agent.
Unlike polecats (ephemeral), you have a persistent identity.
You work directly for the Overseer (the human).
Your work style:
- Handle design work, architecture discussions
- Iterative development with feedback loops
- Can sling work to polecats for implementation
- Maintain context across many sessions via handoff
You can:
- gt sling <bead> polecat - Delegate implementation
- gt convoy create - Start tracking work
- gt mail mayor "status update" - Keep mayor informed
- gt handoff - Gracefully continue in new session
GUPP applies but you often wait for Overseer input.
"""
# =============================================================================
# BLOCK DEFINITIONS: Reusable Gas Town Workflows
# =============================================================================
# GUPP Check: The core propulsion check every worker runs
block gupp_check(worker_name):
session "Check if {worker_name} has work hooked"
prompt: """
Read .prose/gas-town/hooks/{worker_name}.json
If hook has a molecule, return the first uncompleted step.
If hook is empty, return "NO_WORK".
"""
# Patrol Step: Execute a single patrol step
block patrol_step(patrol_name, step_number, step_description):
session "{patrol_name} patrol step {step_number}: {step_description}"
session "Update patrol state with step {step_number} completion"
prompt: """
Update .prose/gas-town/patrol-state.json:
- Set {patrol_name}.current_step = {step_number}
- Set {patrol_name}.last_completed = now()
- If all steps done, set {patrol_name}.patrol_complete = true
"""
# Sling Work: Send work to a worker's hook
block sling_work(bead_id, target_worker):
session "Sling bead {bead_id} to {target_worker}"
prompt: """
1. Read .prose/gas-town/beads/{bead_id}.json
2. Add to .prose/gas-town/hooks/{target_worker}.json
3. Send nudge message to {target_worker}
4. Return confirmation
"""
# Create Convoy: Start tracking a unit of work
block create_convoy(convoy_name, initial_beads):
session "Create convoy: {convoy_name}"
prompt: """
1. Generate convoy ID (timestamp + random)
2. Create .prose/gas-town/convoys/{convoy_id}.json with:
- name: {convoy_name}
- status: "active"
- beads: {initial_beads}
- created: now()
3. Return convoy ID
"""
# Land Convoy: Mark a convoy as complete
block land_convoy(convoy_id):
session "Land convoy {convoy_id}"
prompt: """
1. Update .prose/gas-town/convoys/{convoy_id}.json:
- status: "landed"
- landed_at: now()
2. Notify Mayor that convoy has landed
3. Archive convoy to .prose/gas-town/convoys/archive/
"""
# Handoff: Gracefully transition to new session
# Note: For persistent agents (persist: true/project), use `resume:` instead
# of this block - it handles memory loading automatically.
block handoff(worker_name, continuation_notes):
session "{worker_name} preparing handoff"
prompt: """
1. Write continuation state to hook:
.prose/gas-town/hooks/{worker_name}.json
Include: {continuation_notes}
2. Send mail to self with handoff summary
3. Signal ready for session restart
"""
session "Execute gt handoff to restart session"
# =============================================================================
# GT COMMANDS: Core Gas Town Operations
# =============================================================================
# gt nudge: Wake up a worker that may be stuck
# Workers sometimes don't follow GUPP automatically - nudge kicks them
block gt_nudge(worker_name):
session "Nudge {worker_name} to check hook and continue"
prompt: """
Send wake-up signal to {worker_name}:
1. Send tmux notification to worker's pane
2. Message content: "GUPP check - if work on hook, run it"
3. Log nudge to activity feed
4. Return confirmation
The nudge bypasses Claude Code's politeness - worker will
check hook regardless of what you type.
"""
# gt seance: Talk to a worker's predecessor (dead ancestor)
# Uses Claude Code's /resume to communicate with previous sessions
block gt_seance(worker_name, question):
session "Seance: {worker_name} talking to predecessor"
prompt: """
Talk to {worker_name}'s previous session:
1. Find last session ID from .prose/gas-town/workers/{worker_name}.json
2. Use /resume to reconnect to that session
3. Ask: "{question}"
4. Capture the response
5. Return findings to current session
This is useful when:
- State was lost during handoff
- Predecessor said "I left X for you" but you can't find it
- Need context from previous work
"""
# gt mail send: Send message to a worker's inbox
block gt_mail_send(from_worker, to_worker, message):
session "Mail: {from_worker} -> {to_worker}"
prompt: """
Send mail message:
1. Create mail entry with timestamp, from, to, message
2. Append to .prose/gas-town/rigs/*/mail/{to_worker}.json
(or town-level mail for town workers)
3. If to_worker is active, send nudge
4. Log to activity feed
5. Return message ID
"""
# gt mail check: Read messages from inbox
block gt_mail_check(worker_name):
session "Check mail for {worker_name}"
prompt: """
Read mail inbox:
1. Read .prose/gas-town/rigs/*/mail/{worker_name}.json
2. Also check town-level mail
3. Return unread messages sorted by timestamp
4. Mark as read after returning
"""
# =============================================================================
# WISP OPERATIONS: Ephemeral Orchestration Beads
# =============================================================================
# Create a wisp (ephemeral bead - not persisted to Git)
block create_wisp(wisp_type, content):
session "Create wisp: {wisp_type}"
prompt: """
Create ephemeral bead (wisp):
1. Generate wisp ID (timestamp + random)
2. Write to .prose/gas-town/wisps/{wisp_id}.json:
- type: {wisp_type}
- content: {content}
- created: now()
- ephemeral: true
3. DO NOT add to Git staging
4. Return wisp ID
Wisps are for:
- Patrol orchestration
- Temporary workflow state
- High-velocity operations that would pollute Git
"""
# Burn a wisp (destroy after use)
block burn_wisp(wisp_id, create_digest):
session "Burn wisp {wisp_id}"
prompt: """
Destroy ephemeral bead:
1. Read .prose/gas-town/wisps/{wisp_id}.json
2. If {create_digest} is true:
- Squash to single-line summary
- Append to .prose/gas-town/wisp-digest.jsonl (this IS in Git)
3. Delete the wisp file
4. Return confirmation
"""
# =============================================================================
# ACTIVITY FEED: Live Status Dashboard
# =============================================================================
# Log to activity feed
block log_activity(worker_name, activity_type, details):
session "Log activity: {worker_name} - {activity_type}"
prompt: """
Append to activity feed:
1. Create entry:
- timestamp: now()
- worker: {worker_name}
- type: {activity_type}
- details: {details}
2. Append to .prose/gas-town/activity-feed.jsonl
3. If watching dashboard is active, send update
"""
# Read activity feed
block get_activity_feed(since_timestamp, worker_filter):
session "Get activity feed"
prompt: """
Read activity feed:
1. Read .prose/gas-town/activity-feed.jsonl
2. Filter to entries after {since_timestamp}
3. If {worker_filter} specified, filter to that worker
4. Return entries (most recent first, limit 100)
"""
# =============================================================================
# SWARM OPERATIONS: Polecat Allocation and Management
# =============================================================================
# Spawn a swarm of polecats for a convoy
block spawn_swarm(convoy_id, bead_ids, max_polecats):
session "Spawn swarm for convoy {convoy_id}"
prompt: """
Allocate polecats to work on convoy:
1. Read available polecat slots (max {max_polecats}, usually 30)
2. For each bead in {bead_ids}:
- Check if dependencies are met
- If ready, allocate a polecat
- Sling bead to polecat's hook
3. Create swarm tracking entry:
.prose/gas-town/convoys/{convoy_id}/swarm.json
4. Notify Witness of new swarm
5. Return swarm status (polecats allocated, beads queued)
"""
# Check swarm health
block check_swarm_health(convoy_id):
session "Check swarm health for {convoy_id}"
prompt: """
Assess swarm status:
1. Read .prose/gas-town/convoys/{convoy_id}/swarm.json
2. For each allocated polecat:
- Check last_activity timestamp
- Check hook status (working/stuck/complete)
- Check if context exhaustion imminent
3. Return health report:
- active_polecats: N
- stuck_polecats: [list]
- beads_completed: N
- beads_remaining: N
- estimated_completion: timestamp
"""
# Recycle exhausted polecats (prevent context exhaustion)
block recycle_polecat(polecat_id, rig_name):
session "Recycle polecat {polecat_id}"
prompt: """
Gracefully recycle polecat before context exhaustion:
1. Read current molecule state from hook
2. Trigger handoff for polecat
3. Wait for new session to spin up
4. Verify hook is picked up by new session
5. Update swarm tracking
6. Return confirmation
"""
# =============================================================================
# FORMULA AND MOLECULE OPERATIONS
# =============================================================================
# Cook a formula into a protomolecule
block cook_formula(formula_name):
session "Cook formula: {formula_name}"
prompt: """
Transform formula into protomolecule:
1. Read .prose/gas-town/formulas/{formula_name}.toml
2. Parse formula structure (steps, loops, gates)
3. Expand loops and conditionals
4. Generate protomolecule beads (templates)
5. Write to .prose/gas-town/protomolecules/{formula_name}/
6. Return protomolecule ID
"""
# Instantiate a protomolecule into a working molecule
block instantiate_molecule(protomolecule_id, variables):
session "Instantiate molecule from {protomolecule_id}"
prompt: """
Create working molecule from template:
1. Read .prose/gas-town/protomolecules/{protomolecule_id}/
2. Copy all template beads
3. Perform variable substitution with {variables}
4. Generate unique IDs for each bead
5. Link beads according to dependency graph
6. Write molecule to rig's bead database
7. Return molecule ID and first step
"""
# The "Rule of Five" formula composer
# Makes each step get reviewed 4 additional times (5 total)
block compose_rule_of_five(base_molecule_id):
session "Apply Rule of Five to molecule"
prompt: """
Wrap molecule with 5x review pattern:
1. Read molecule {base_molecule_id}
2. For each step in molecule:
- Keep original step (review #1)
- Add 4 review steps with different focus:
* Review #2: Correctness focus
* Review #3: Edge cases focus
* Review #4: Performance focus
* Review #5: Security focus
3. Chain reviews to gate original step completion
4. Return enhanced molecule ID
This generates superior outcomes per Jeffrey Emanuel's observation.
"""
# =============================================================================
# RIG MANAGEMENT
# =============================================================================
# Add a rig to Gas Town management
block gt_rig_add(rig_name, repo_path):
session "Add rig: {rig_name}"
prompt: """
Add project to Gas Town:
1. Verify {repo_path} is a valid Git repo
2. Create .prose/gas-town/rigs/{rig_name}/ structure:
- rig-beads.jsonl
- hooks/
- mail/
- polecats/
- merge-queue.json
- plugins/
3. Initialize witness for this rig
4. Initialize refinery for this rig
5. Add to town's rig registry
6. Return confirmation
"""
# List all rigs
block gt_rig_list:
session "List all rigs"
prompt: """
List Gas Town rigs:
1. Read .prose/gas-town/rigs/
2. For each rig, report:
- name
- repo path
- active polecats
- pending MRs
- active convoys
3. Return formatted list
"""
# War Rig: A rig's contribution to a cross-rig convoy
block war_rig_status(rig_name, convoy_id):
session "War Rig status: {rig_name} for {convoy_id}"
prompt: """
Get rig's contribution to cross-rig convoy:
1. Read convoy {convoy_id}
2. Filter to beads assigned to {rig_name}
3. Report:
- Beads completed
- Beads in progress
- MRs pending merge
- Blockers
4. Return War Rig summary
"""
# =============================================================================
# THE DEACON'S PATROL: Town-level orchestration heartbeat
# =============================================================================
block deacon_patrol:
# Step 1: Check town health
do patrol_step("deacon", 1, "Check town health")
session: deacon
prompt: """
Scan Gas Town health:
- Read .prose/gas-town/patrol-state.json
- Check all workers have recent activity
- Identify any stuck or crashed workers
- Return health report
"""
# Step 2: Propagate DYFJ signal
do patrol_step("deacon", 2, "Propagate DYFJ to witnesses")
parallel (on-fail: "continue"):
session "Nudge witness for rig 1"
prompt: "Send DYFJ signal to witness-1"
session "Nudge witness for rig 2"
prompt: "Send DYFJ signal to witness-2"
# Step 3: Run town-level plugins
do patrol_step("deacon", 3, "Run town plugins")
let plugins_needed = session "Check for pending town plugins"
prompt: "Read .prose/gas-town/plugins/town/*.json, return pending"
if **there are plugins that need to run**:
session: deacon
prompt: "Sling plugin work to an available Dog"
context: plugins_needed
# Step 4: Cleanup and maintenance
do patrol_step("deacon", 4, "Delegate maintenance to Dogs")
session: deacon
prompt: """
Check if maintenance needed:
- Stale branches older than 7 days
- Orphaned convoys
- Log rotation
If needed, mail a Dog with maintenance tasks.
"""
# Step 5: Set backoff for next patrol
do patrol_step("deacon", 5, "Calculate patrol backoff")
session: deacon
prompt: """
Check activity level:
- If lots of active work: backoff = 30 seconds
- If moderate activity: backoff = 2 minutes
- If idle: double previous backoff (max 10 minutes)
Write backoff to .prose/gas-town/patrol-state.json
"""
# =============================================================================
# THE WITNESS'S PATROL: Rig-level swarm health monitoring
# =============================================================================
block witness_patrol(rig_name):
# Step 1: Check polecat wellbeing
do patrol_step("witness-{rig_name}", 1, "Check polecat health")
let polecat_status = session: witness
prompt: """
For rig {rig_name}, check all active polecats:
- Read .prose/gas-town/polecats/{rig_name}/*.json
- Check last_activity timestamp
- Identify stuck polecats (no activity > 5 minutes)
Return list of stuck polecats.
"""
# Step 2: Nudge stuck polecats
if **there are stuck polecats**:
do patrol_step("witness-{rig_name}", 2, "Nudge stuck polecats")
for polecat in polecat_status:
session: witness
prompt: "Execute gt nudge {polecat} for rig {rig_name}"
context: polecat
# Step 3: Check refinery progress
do patrol_step("witness-{rig_name}", 3, "Check merge queue")
let mq_status = session: witness
prompt: """
Check .prose/gas-town/merge-queue.json for {rig_name}:
- How many MRs pending?
- Is refinery processing?
- Any stuck MRs (age > 30 minutes)?
Return MQ health status.
"""
if **the merge queue is stuck**:
session: witness
prompt: "Nudge the refinery to process MQ for {rig_name}"
context: mq_status
# Step 4: Peek at Deacon
do patrol_step("witness-{rig_name}", 4, "Peek at Deacon")
session: witness
prompt: """
Quick check on Deacon:
- Read .prose/gas-town/patrol-state.json
- Is Deacon's last patrol > 10 minutes ago?
- If so, send alert to Mayor
"""
# Step 5: Run rig plugins
do patrol_step("witness-{rig_name}", 5, "Run rig plugins")
session: witness
prompt: """
Check .prose/gas-town/plugins/rig/{rig_name}/*.json
Run any pending plugins for this rig.
"""
# Step 6: Recycle exhausted polecats
do patrol_step("witness-{rig_name}", 6, "Recycle polecats")
session: witness
prompt: """
Check polecat session lengths:
- Any polecat running > 45 minutes?
- If so, trigger handoff before context exhaustion
- Ensure work continues on new session
"""
# =============================================================================
# THE REFINERY'S PATROL: Merge Queue Processing
# =============================================================================
block refinery_patrol(rig_name):
# Preflight: Clean workspace
do patrol_step("refinery-{rig_name}", 1, "Preflight checks")
session: refinery
prompt: """
Preflight for {rig_name}:
1. git fetch origin
2. git checkout main && git pull
3. Clean any uncommitted changes
4. Verify workspace is ready
"""
# Main loop: Process MQ until empty
do patrol_step("refinery-{rig_name}", 2, "Process merge queue")
loop until **the merge queue is empty** (max: 20):
let next_mr = session: refinery
prompt: """
Read .prose/gas-town/merge-queue.json
Get highest priority MR for {rig_name}
Return MR details or "EMPTY" if none.
"""
if **there is an MR to process**:
# Process single MR
try:
session: refinery
prompt: """
Process MR for {rig_name}:
1. git checkout {next_mr.branch}
2. git rebase main
3. Run tests: npm test / pytest / cargo test
4. Run lint and type checks
5. If all pass, merge to main
6. Update convoy status
"""
context: next_mr
retry: 2
backoff: "linear"
session: refinery
prompt: """
MR merged successfully:
1. Remove from .prose/gas-town/merge-queue.json
2. Delete branch
3. Update convoy progress
4. Notify polecat of completion
"""
context: next_mr
catch as merge_error:
# Handle merge conflicts
choice **the type of merge failure**:
option "Conflict - needs reimplementation":
session: refinery
prompt: """
Merge conflict detected. Create escalation:
1. Mark MR as "needs_reimplementation"
2. Create new bead for conflict resolution
3. Sling to a new polecat
4. Notify Witness of the situation
"""
context: merge_error
option "Test failure - needs fix":
session: refinery
prompt: """
Tests failed after merge:
1. Git reset the merge
2. Create fix-tests bead
3. Assign back to original polecat
4. Add to same convoy
"""
context: merge_error
option "Unrecoverable - escalate":
session: refinery
prompt: """
Cannot process MR:
1. Mark as "escalated" in MQ
2. Send urgent mail to Mayor
3. Add to convoy blockers
4. Continue with next MR
"""
context: merge_error
# Postflight: Cleanup and report
do patrol_step("refinery-{rig_name}", 3, "Postflight")
session: refinery
prompt: """
Postflight for {rig_name}:
1. Report MQ processing summary
2. Update patrol state with completion time
3. Check if any convoys can be landed
4. Set backoff based on MQ activity
"""
# =============================================================================
# BOOT THE DOG: Special Dog that watches the Deacon
# =============================================================================
block boot_check:
session: dog
prompt: """
You are Boot the Dog. Your only job: check on the Deacon.
Read .prose/gas-town/patrol-state.json
Check deacon.last_patrol timestamp.
Decision:
- If < 2 min ago: Deacon is fine. Go back to sleep.
- If 2-5 min ago: Send gentle nudge to Deacon.
- If 5-10 min ago: Send firm DYFJ to Deacon.
- If > 10 min ago: Restart Deacon session.
Execute your decision, then sleep until next 5-minute wake.
"""
# =============================================================================
# CONVOY WORKFLOW: Full lifecycle of a work unit
# =============================================================================
block convoy_workflow(convoy_name, work_description, target_rig):
# Phase 1: Mayor receives and plans (first call uses session:)
let plan = session: mayor
prompt: """
New convoy requested: {convoy_name}
Work: {work_description}
Rig: {target_rig}
1. Break down into implementable beads
2. Identify dependencies between beads
3. Estimate polecat count needed
4. Create convoy structure
"""
# Phase 2: Create convoy and beads
do create_convoy(convoy_name, plan)
# Subsequent Mayor calls use resume: to load memory
let beads = resume: mayor
prompt: """
Create individual beads for convoy {convoy_name}:
1. Write each bead to .prose/gas-town/beads/
2. Link beads to convoy
3. Set initial status to "ready"
Return list of bead IDs.
"""
context: plan
# Phase 3: Swarm the work
resume: mayor
prompt: """
Initiate swarm for convoy {convoy_name}:
1. Determine optimal polecat count (max 30)
2. Sling work to polecats based on dependencies
3. Notify Witness to monitor swarm
4. Return swarm status
"""
context: beads
# Phase 4: Let the swarm run (monitored by Witness)
loop until **all convoy beads are complete or blocked** (max: 50):
# Witness patrol handles the actual monitoring
do witness_patrol(target_rig)
# Check convoy status
let convoy_status = resume: mayor
prompt: """
Check convoy {convoy_name} status:
- Read .prose/gas-town/convoys/{convoy_name}.json
- Count completed vs pending beads
- Check for blockers
Return status summary.
"""
if **there are blocked beads that need attention**:
resume: mayor
prompt: """
Handle blocked beads in convoy:
1. Analyze block reasons
2. Create unblock beads if needed
3. Escalate to Overseer if human decision required
"""
context: convoy_status
# Phase 5: Refinery merges everything
loop until **all MRs from convoy are merged** (max: 30):
do refinery_patrol(target_rig)
# Phase 6: Land the convoy
do land_convoy(convoy_name)
resume: mayor
prompt: """
Convoy {convoy_name} has landed!
1. Generate completion summary
2. Notify Overseer
3. Archive convoy artifacts
4. Update rig statistics
"""
# =============================================================================
# POLECAT LIFECYCLE: Ephemeral worker execution
# =============================================================================
block polecat_lifecycle(polecat_id, rig_name):
# Startup: GUPP check
let hook_work = do gupp_check("polecat-{polecat_id}")
if **there is no work on hook**:
session: polecat
prompt: """
No work on hook. Options:
1. Check mail for new assignments
2. Ask Witness for work
3. Go idle (decommission after 5 min idle)
"""
else:
# Main work loop: Execute molecule
loop until **molecule is complete** (max: 100):
let current_step = session: polecat
prompt: """
Read current molecule step from hook.
Return step details:
- step_id
- description
- acceptance_criteria
- dependencies (must be complete first)
"""
context: hook_work
if **dependencies are not met**:
session: polecat
prompt: """
Dependencies not ready. Options:
1. Work on a different bead in molecule
2. Wait and check again in 30 seconds
3. Report blocker to Witness
"""
context: current_step
else:
# Execute the step
try:
session: polecat
prompt: """
Execute molecule step:
{current_step.description}
Acceptance criteria:
{current_step.acceptance_criteria}
Work until criteria are met, then mark step complete.
"""
context: current_step
retry: 2
backoff: "exponential"
# Mark step complete
session: polecat
prompt: """
Step complete. Update state:
1. Mark step as complete in molecule
2. Update convoy progress
3. If code changed, prepare MR
4. Move to next step
"""
catch as step_error:
session: polecat
prompt: """
Step failed. Handle error:
1. Log failure details
2. Determine if retryable
3. If not, escalate to Witness
4. Update molecule state
"""
context: step_error
# Check if should hand off (context exhaustion prevention)
if **session is getting long (> 40 messages)**:
do handoff("polecat-{polecat_id}", "Continue molecule execution")
# Molecule complete: Submit MR if needed
let has_changes = session: polecat
prompt: "Check if there are uncommitted code changes. Return true/false."
if **there are code changes to submit**:
session: polecat
prompt: """
Prepare Merge Request:
1. Stage all changes: git add -A
2. Create atomic commit with descriptive message
3. Push branch to origin
4. Add MR to .prose/gas-town/merge-queue.json
5. Notify Refinery
"""
# Decommission
session: polecat
prompt: """
Polecat {polecat_id} decommissioning:
1. Clear hook
2. Update convoy with completion status
3. Send completion mail to Witness
4. Mark self as available for reuse
"""
# =============================================================================
# POLECAT WORKFLOW VARIANTS: Different quality levels
# =============================================================================
# Standard polecat workflow (fast, minimal review)
block polecat_workflow_standard(bead_id):
session: polecat
prompt: """
Standard workflow for bead {bead_id}:
1. Read bead acceptance criteria
2. Implement the change
3. Self-review for obvious issues
4. Submit MR
Fast but minimal quality gates.
"""
# "Shiny" polecat workflow (extra code review)
block polecat_workflow_shiny(bead_id):
session: polecat
prompt: "Implement bead {bead_id}"
session: polecat
prompt: """
Shiny review pass 1: Code correctness
- Does the implementation match requirements?
- Are there any logical errors?
- Fix any issues found.
"""
session: polecat
prompt: """
Shiny review pass 2: Code quality
- Is the code readable and maintainable?
- Does it follow project conventions?
- Fix any issues found.
"""
session: polecat
prompt: "Submit MR with shiny review complete"
# "Chrome" polecat workflow (extra review + testing)
block polecat_workflow_chrome(bead_id):
session: polecat
prompt: "Implement bead {bead_id}"
# All shiny review passes
session: polecat
prompt: "Chrome review pass 1: Correctness check"
session: polecat
prompt: "Chrome review pass 2: Quality check"
session: polecat
prompt: "Chrome review pass 3: Edge cases check"
# Extra chrome passes
session: polecat
prompt: """
Chrome review pass 4: Test coverage
- Write unit tests for new code
- Ensure edge cases are tested
- Run tests locally
"""
session: polecat
prompt: """
Chrome review pass 5: Security check
- Check for injection vulnerabilities
- Verify input validation
- Check for data exposure risks
"""
session: polecat
prompt: "Submit MR with chrome review complete"
# =============================================================================
# CV CHAINS: Polecat Work Credits
# =============================================================================
# Record polecat completion to CV chain (credited work history)
block record_cv_completion(polecat_id, bead_id, convoy_id):
session "Record CV completion for polecat {polecat_id}"
prompt: """
Add completion to polecat's CV chain:
1. Read .prose/gas-town/workers/polecats/{polecat_id}.json
2. Append to cv_chain:
- bead_id: {bead_id}
- convoy_id: {convoy_id}
- completed_at: now()
- outcome: success/partial/escalated
3. Update statistics:
- total_completions
- success_rate
- average_duration
4. Save updated worker record
CV chains provide:
- Work attribution (who did what)
- Performance metrics
- Trust scoring for assignment prioritization
"""
# Get polecat's CV summary
block get_cv_summary(polecat_id):
session "Get CV summary for {polecat_id}"
prompt: """
Summarize polecat's work history:
1. Read .prose/gas-town/workers/polecats/{polecat_id}.json
2. Return:
- Total completions
- Success rate
- Recent convoy contributions
- Specializations (detected from bead types)
- Trust score
"""
# =============================================================================
# MAIN: Gas Town Startup and Operation
# =============================================================================
# Initialize Gas Town state directories
session "Initialize Gas Town persistent state"
prompt: """
Create Gas Town state structure:
.prose/gas-town/
├── town-beads.jsonl # Town-level orchestration beads
├── activity-feed.jsonl # Live activity stream
├── patrol-state.json # Patrol agent states
├── wisp-digest.jsonl # Burned wisp summaries
├── workers/ # Persistent worker identities
│ ├── mayor.json
│ ├── deacon.json
│ ├── dogs/
│ │ └── boot.json
│ └── polecats/ # Polecat CV chains
├── convoys/ # Work orders
│ ├── active/
│ └── archive/
├── formulas/ # Workflow templates (TOML)
├── protomolecules/ # Cooked templates
├── wisps/ # Ephemeral beads (NOT in Git)
├── plugins/
│ └── town/ # Town-level plugins
└── rigs/ # Per-project state
└── {rig-name}/
├── rig-beads.jsonl # Project issues
├── merge-queue.json # Pending MRs
├── hooks/ # Worker hooks (GUPP)
├── mail/ # Worker inboxes
├── polecats/ # Per-rig polecat state
└── plugins/ # Rig-level plugins
Initialize all files with empty/default values.
Add .prose/gas-town/wisps/ to .gitignore (ephemeral).
"""
# Start the Mayor
session: mayor
prompt: """
Gas Town Mayor starting up.
GUPP Check: Read .prose/gas-town/hooks/mayor.json
If work hooked, begin immediately.
Otherwise, greet the Overseer and await instructions.
Available commands:
- "Create convoy for: <description>" - Start new work unit
- "Sling <bead> to <worker>" - Assign work
- "Status" - Show town status
- "Let's hand off" - Gracefully restart
"""
# Start patrol agents in background (parallel)
parallel (on-fail: "continue"):
# Deacon patrol loop
loop (max: 1000):
try:
do deacon_patrol
catch:
session "Deacon patrol error - will retry"
session "Wait for deacon backoff period"
prompt: "Read backoff from patrol-state.json and wait"
# Boot the Dog wakes every 5 minutes
loop (max: 1000):
do boot_check
session "Boot sleeping for 5 minutes"
prompt: "Wait 5 minutes before next Deacon check"
# =============================================================================
# EXAMPLE: Running a Convoy
# =============================================================================
# This block shows how an Overseer would use Gas Town
block example_convoy:
# Overseer tells Mayor what to build
session: mayor
prompt: """
Overseer request: "Add dark mode to the dashboard"
As Mayor:
1. Acknowledge the request
2. Break it down into implementable pieces
3. Create a convoy to track it
4. Swarm polecats on the work
5. Report when convoy lands
"""
# Mayor creates and manages the convoy
do convoy_workflow(
"dark-mode-dashboard",
"Add dark mode toggle and theme support to the dashboard",
"main-app"
)
# When done, Mayor reports back
session: mayor
prompt: """
Report convoy completion to Overseer:
- What was implemented
- Any issues encountered
- Files changed
- Ready for review
"""
# =============================================================================
# EXAMPLE: Direct Crew Work
# =============================================================================
# For design/architecture work, use Crew instead of polecats
block crew_design_session(topic):
# First invocation starts fresh design session
session: crew
prompt: """
Design session for: {topic}
As a Crew member, engage in iterative design:
1. Understand the problem space
2. Propose architecture options
3. Discuss trade-offs with Overseer
4. Document decisions
5. Optionally sling implementation to polecats
This is interactive - wait for Overseer input.
"""
loop until **design is finalized** (max: 20):
# Subsequent calls resume with memory
resume: crew
prompt: """
Continue design iteration:
- Address Overseer feedback
- Refine the design
- When ready, ask if should proceed to implementation
"""
if **Overseer wants to proceed with implementation**:
resume: crew
prompt: """
Create implementation convoy:
1. Convert design into beads
2. Create convoy
3. Sling to polecats
4. Return convoy ID to track
"""
# =============================================================================
# EXAMPLE: Hanoi Towers (MAKER Problem)
# =============================================================================
#
# Gas Town can solve arbitrarily long sequential workflows.
# The Towers of Hanoi problem (from the MAKER paper) demonstrates this:
# - 10-disc Hanoi: ~1000 steps (runs in minutes)
# - 20-disc Hanoi: ~1,000,000 steps (runs in ~30 hours)
#
# LLMs traditionally fail after a few hundred steps (per MAKER paper).
# Gas Town's molecular workflows make this trivial via NDI.
# Generate Hanoi formula (creates workflow from mathematical formula)
block generate_hanoi_formula(num_discs):
session "Generate Hanoi formula for {num_discs} discs"
prompt: """
Generate Towers of Hanoi workflow formula:
For {num_discs} discs, generate (2^n - 1) move steps.
Each step is a bead:
- ID: hanoi-move-{step_number}
- Description: "Move disc from peg {from} to peg {to}"
- Acceptance: "Disc moved, state updated"
- Depends on: previous step
Write to .prose/gas-town/formulas/hanoi-{num_discs}.toml
This demonstrates Gas Town's ability to handle
arbitrarily long workflows via NDI (Nondeterministic Idempotence).
Crashes don't matter - just resume from last completed step.
"""
# Run the Hanoi demonstration
block run_hanoi_demo(num_discs):
# Generate the formula
do generate_hanoi_formula(num_discs)
# Cook into protomolecule
do cook_formula("hanoi-{num_discs}")
# Instantiate into working molecule
let hanoi_mol = do instantiate_molecule(
"hanoi-{num_discs}",
{"discs": num_discs}
)
# Create convoy to track
do create_convoy("hanoi-{num_discs}-demo", hanoi_mol)
# Sling to a polecat (single worker for sequential)
do sling_work(hanoi_mol, "polecat-hanoi")
# The polecat will work through all steps
# Crashes are fine - NDI ensures eventual completion
session: mayor
prompt: """
Hanoi convoy started for {num_discs} discs.
- Steps: 2^{num_discs} - 1
- Est. completion: varies by disc count
- Polecat will checkpoint progress in molecule
- Monitor via activity feed
"""
# =============================================================================
# EXAMPLE: Full Production Workflow
# =============================================================================
# This shows a realistic production workflow using all Gas Town features
block production_feature_workflow(feature_name, rig_name):
# Phase 1: Design with Crew (first call)
do log_activity("overseer", "feature_start", feature_name)
let design = session: crew
prompt: """
Design phase for: {feature_name}
1. Understand requirements
2. Research existing code
3. Propose architecture
4. Get Overseer approval
"""
# Phase 2: Create convoy with chrome-level quality (first Mayor call)
let plan = session: mayor
prompt: """
Create implementation plan for {feature_name}:
1. Break into implementable beads
2. Add dependencies
3. Select chrome workflow (highest quality)
4. Estimate polecat count
"""
context: design
do create_convoy("{feature_name}-impl", plan)
# Phase 3: Spawn swarm with chrome workflow
resume: mayor
prompt: """
Spawn chrome-quality swarm:
1. Allocate polecats (use trust scores from CVs)
2. Assign chrome workflow to each bead
3. Notify Witness
"""
context: plan
# Phase 4: Monitor progress (patrols handle the rest)
loop until **all beads complete** (max: 100):
do check_swarm_health("{feature_name}-impl")
if **any polecats stuck**:
resume: witness
prompt: "Nudge stuck polecats, use seance if needed"
if **any polecats near context limit**:
resume: witness
prompt: "Recycle exhausted polecats"
# Phase 5: Merge all MRs
loop until **all MRs merged** (max: 50):
do refinery_patrol(rig_name)
# Phase 6: Land and celebrate
do land_convoy("{feature_name}-impl")
resume: mayor
prompt: """
Feature {feature_name} complete!
1. Generate release notes
2. Update documentation
3. Notify Overseer
4. Record CV completions for all polecats
"""
# =============================================================================
# EXAMPLE: Cross-Rig Convoy (War Rigs)
# =============================================================================
# When a feature spans multiple projects
block cross_rig_convoy(feature_name, rig_list):
# Create convoy that spans multiple rigs (first Mayor call)
session: mayor
prompt: """
Cross-rig convoy for {feature_name}:
Rigs involved: {rig_list}
1. Identify work for each rig (War Rigs)
2. Create beads in each rig's database
3. Link with cross-rig dependencies
4. Coordinate witnesses across rigs
"""
# Spawn witnesses for each rig
parallel for rig in rig_list:
session: witness
prompt: "Initialize War Rig monitoring for {rig} in convoy {feature_name}"
# Swarm all rigs in parallel
parallel for rig in rig_list:
do spawn_swarm("{feature_name}", "war-rig-{rig}-beads", 10)
# Monitor War Rig contributions
loop until **all War Rigs complete** (max: 200):
parallel for rig in rig_list:
do war_rig_status(rig, "{feature_name}")
if **any War Rig blocked**:
resume: mayor
prompt: "Coordinate cross-rig blocker resolution"
# Land the cross-rig convoy
do land_convoy("{feature_name}")
resume: mayor
prompt: """
Cross-rig convoy {feature_name} landed!
War Rig summary for each rig: {rig_list}
"""
# =============================================================================
# GAS TOWN STATUS DASHBOARD
# =============================================================================
block gt_status:
parallel:
town_health = session "Check town health"
prompt: """
Town-level status:
- Deacon patrol status
- Dogs status
- Active convoys (town-level)
"""
rig_health = session "Check rig health"
prompt: """
Per-rig status:
- Read .prose/gas-town/rigs/
- For each rig: polecats, MQ depth, witnesses
"""
activity = do get_activity_feed("last_hour", "")
session: mayor
prompt: """
Gas Town Status Report:
TOWN:
{town_health}
RIGS:
{rig_health}
RECENT ACTIVITY:
{activity}
Recommendations:
- Any workers needing attention?
- Any convoys blocked?
- Resource utilization?
"""
context: { town_health, rig_health, activity }
# =============================================================================
# RUN EXAMPLES (commented out - uncomment to execute)
# =============================================================================
# Basic examples:
# do example_convoy
# do crew_design_session("API redesign for v2")
# Advanced examples:
# do run_hanoi_demo(10) # ~1000 steps, runs in minutes
# do production_feature_workflow("user-auth", "main-app")
# do cross_rig_convoy("unified-search", ["frontend", "backend", "search-service"])
# do gt_status