# 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
