How the Refinery Implements the Merge Queue Strategy in Gas Town
The Refinery employs a sequential rebase-and-fast-forward merge workflow that processes polecat branches one at a time from a Beads-managed queue, ensuring linear history through strict test gating and automated conflict resolution.
The merge queue strategy in the gastownhall/gastown repository centers on the Refinery, an automated processor that eliminates parallel merge conflicts by strictly serializing integration work. Unlike traditional merge queues that attempt concurrent processing, the Refinery guarantees a clean Git history by rebasing each branch onto the current target before applying a fast-forward-only merge. This deterministic approach is codified in internal/templates/roles/refinery.md.tmpl and implemented across the Go source tree.
Core Principles of the Refinery Merge Queue Strategy
Single-Source of Truth via Beads Commands
The Refinery never interrogates raw git branch output to determine pending work. Instead, it relies exclusively on the Beads command gt mq list <rig> as the authoritative source for the ordered merge queue. This command returns polecat branches sequenced by priority, dependencies, and timestamps, ensuring that high-priority changes land first without manual intervention.
Sequential Processing and Fast-Forward Only Merges
Each iteration of the Refinery patrol processes exactly one polecat branch. The workflow in internal/templates/roles/refinery.md.tmpl (lines 124-138) mandates:
- Checkout a temporary branch from the polecat branch
- Rebase onto the current target branch (
git rebase origin/<target>) - Execute the configured test suite
- Merge using
git merge --ff-onlyinto the target - Push the updated target
After each successful merge, the target branch advances, forcing the next iteration to rebase onto the new baseline. This sequential rebase-and-fast-forward pattern prevents the "old-target" conflicts common in parallel merge strategies.
Automated Conflict Resolution
When git rebase encounters unresolvable conflicts, the Refinery aborts the operation and triggers a failure protocol. According to the template specification (lines 101-110), the system executes git rebase --abort, reopens the source issue via bd update <source-issue> --status=open, notifies the Witness role with a MERGE_FAILED mail, closes the merge request, and deletes the polecat branch.
Test Gating Requirements
Before any fast-forward merge completes, the branch must pass the configured test pipeline defined in Beads. Failures are categorized either as branch-specific issues (triggering the conflict resolution protocol) or as pre-existing infrastructure problems (filed as Beads bugs). This gate prevents broken code from entering the target branch.
Step-by-Step Refinery Patrol Workflow
The concrete implementation follows the patrol molecule (mol-refinery-patrol) defined in the role template. The process begins immediately upon receipt of a MERGE_READY mail sent by the Witness role, implementing a "Hook → Execute" model with no manual approval delays.
The execution flow in internal/protocol/refinery_handlers.go handles these steps:
# 1. Check for MERGE_READY signal
gt mail inbox | grep MERGE_READY && gt mail read <msg-id>
# 2. Obtain ordered queue from Beads (single-source of truth)
gt mq list my-rig
# 3. Process next branch (example: polecat/feat-123)
git checkout -b temp polecat/feat-123
git rebase origin/main
# 4. Run test suite (commands defined in Beads)
./scripts/typecheck && ./scripts/lint && go test ./...
# 5. Fast-forward merge and push
git checkout main
git merge --ff-only temp
git push origin main
# 6. Cleanup
git branch -d temp
git branch -d polecat/feat-123
Handling Merge Conflicts and Failures
When conflicts arise during the rebase phase, the Refinery distinguishes between resolvable and unresolvable states. For resolvable conflicts, manual intervention is not supported—the branch must be updated upstream and resubmitted. For unresolvable conflicts, the automated failure protocol executes:
git checkout -b temp polecat/feat-123
git rebase origin/main
# Conflict appears
git status
# If unresolvable:
git rebase --abort
bd update <source-issue> --status=open
gt mq close <mr-id> --reason="Unresolvable conflicts"
gt mail send my-rig/witness -s "MERGE_FAILED" \
-m "Branch polecat/feat-123 cannot be merged; source issue reopened."
Integration Branch Processing
Integration branches representing large epics receive special treatment in the merge queue strategy. The Refinery never merges these using raw Git commands. Instead, it processes them exclusively through the dedicated Beads command:
gt mq integration land <epic-id>
This command, referenced in internal/templates/roles/refinery.md.tmpl (lines 142-149), ensures that epic-level integration work undergoes additional validation steps before entering the main line of development.
Key Source Files and Implementation
The merge queue strategy is distributed across these critical source files:
internal/templates/roles/refinery.md.tmpl: Human-readable specification defining the patrol molecule, merge logic, and failure handling protocolsinternal/protocol/refinery_handlers.go: Go implementation of mail-driven handlers processingMERGE_READYandMERGE_FAILEDsignalsinternal/cmd/refinery.go: CLI entry point that wires the patrol molecule into the Gas Town daemoninternal/config/roles/refinery.toml: Default configuration for target branches, work directories, and notification settingsgt-model-eval/tests/refinery‑triage.yaml: Test scenarios validating the patrol workflow
Summary
- The Refinery implements a sequential rebase-and-fast-forward merge strategy that processes one branch at a time from the Beads-managed queue obtained via
gt mq list <rig>. - Fast-forward only merges (
--ff-only) guarantee linear history; unresolvable conflicts trigger automatic cleanup, issue reopening, and Witness notification. - Test gating blocks merges that fail the configured pipeline, attributing failures to either the branch or pre-existing infrastructure problems.
- Integration branches require the specialized
gt mq integration land <epic-id>command rather than standard merge operations. - The "Hook → Execute" model ensures immediate processing upon
MERGE_READYmail receipt, eliminating manual approval delays.
Frequently Asked Questions
What happens when a fast-forward merge is not possible in Gas Town?
If git merge --ff-only fails because the branch has diverged from the target in a non-linear fashion, the Refinery treats this as an unresolvable condition. According to internal/templates/roles/refinery.md.tmpl, the system aborts the operation, reopens the source issue, sends a MERGE_FAILED mail to the Witness, closes the merge request, and deletes the polecat branch, leaving manual resolution to the developer.
How does the Refinery determine the order of branches in the merge queue?
The Refinery calls gt mq list <rig> to obtain an ordered list from Beads. This command sorts polecat branches by priority markers, dependency chains, and timestamps, ensuring that urgent or foundational changes merge before dependent work. Raw git branch listings are never used as a source of truth.
What is the difference between regular polecat branches and integration branches?
Regular polecat branches follow the standard sequential rebase-and-merge workflow through the Refinery patrol. Integration branches (epics) bypass raw Git merges entirely and must be landed using the specialized command gt mq integration land <epic-id>, which enforces additional validation steps appropriate for large-scale feature integration.
How does the Refinery handle test failures during the merge process?
Test failures abort the merge attempt immediately. The Refinery, as implemented in internal/protocol/refinery_handlers.go, distinguishes between branch-specific failures (which reopen the source issue and notify the Witness) and infrastructure failures (which generate Beads bug reports). In both cases, the polecat branch is cleaned up and removed from the queue until the underlying issue is fixed.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →