Documentation
¶
Overview ¶
Package refinery provides the merge queue processing agent.
Package refinery provides the merge queue processing agent.
Index ¶
- Constants
- Variables
- func ValidateTransition(from, to MRStatus) error
- type CloseReason
- type Engineer
- func (e *Engineer) Config() *MergeQueueConfig
- func (e *Engineer) IsBeadOpen(beadID string) (bool, error)
- func (e *Engineer) ListBlockedMRs() ([]*mrqueue.MR, error)
- func (e *Engineer) ListReadyMRs() ([]*mrqueue.MR, error)
- func (e *Engineer) LoadConfig() error
- func (e *Engineer) ProcessMR(ctx context.Context, mr *beads.Issue) ProcessResult
- func (e *Engineer) ProcessMRFromQueue(ctx context.Context, mr *mrqueue.MR) ProcessResult
- func (e *Engineer) SetOutput(w io.Writer)
- type FailureType
- type MRStatus
- type Manager
- func (m *Manager) FindMR(idOrBranch string) (*MergeRequest, error)
- func (m *Manager) GetMR(id string) (*MergeRequest, error)
- func (m *Manager) ProcessMR(mr *MergeRequest) MergeResultdeprecated
- func (m *Manager) Queue() ([]QueueItem, error)
- func (m *Manager) RegisterMR(mr *MergeRequest) error
- func (m *Manager) RejectMR(idOrBranch string, reason string, notify bool) (*MergeRequest, error)
- func (m *Manager) Retry(id string, processNow bool) error
- func (m *Manager) SessionName() string
- func (m *Manager) SetOutput(w io.Writer)
- func (m *Manager) Start(foreground bool) error
- func (m *Manager) Status() (*Refinery, error)
- func (m *Manager) Stop() error
- type MergeConfig
- type MergeQueueConfig
- type MergeRequest
- func (mr *MergeRequest) Claim() error
- func (mr *MergeRequest) Close(reason CloseReason) error
- func (mr *MergeRequest) IsClosed() bool
- func (mr *MergeRequest) IsInProgress() bool
- func (mr *MergeRequest) IsOpen() bool
- func (mr *MergeRequest) Reopen() error
- func (mr *MergeRequest) SetStatus(newStatus MRStatus) error
- type MergeResult
- type ProcessResult
- type QueueItem
- type Refinery
- type State
Constants ¶
const ( StateStopped = agent.StateStopped StateRunning = agent.StateRunning StatePaused = agent.StatePaused )
State constants - re-exported from agent package for backwards compatibility.
Variables ¶
var ( ErrNotRunning = errors.New("refinery not running") ErrAlreadyRunning = errors.New("refinery already running") ErrNoQueue = errors.New("no items in queue") )
Common errors
var ( ErrMRNotFound = errors.New("merge request not found") ErrMRNotFailed = errors.New("merge request has not failed") )
Common errors for MR operations
var ( // ErrInvalidTransition is returned when a state transition is not allowed. ErrInvalidTransition = errors.New("invalid state transition") // ErrClosedImmutable is returned when attempting to change a closed MR. ErrClosedImmutable = errors.New("closed merge requests are immutable") )
State transition errors.
Functions ¶
func ValidateTransition ¶
ValidateTransition checks if a state transition from -> to is valid.
Valid transitions:
- open → in_progress (Engineer claims MR)
- in_progress → closed (merge success or rejection)
- in_progress → open (failure, reassign to worker)
- open → closed (manual rejection)
Invalid:
- closed → anything (immutable once closed)
Types ¶
type CloseReason ¶
type CloseReason string
CloseReason indicates why a merge request was closed.
const ( // CloseReasonMerged means the MR was successfully merged. CloseReasonMerged CloseReason = "merged" // CloseReasonRejected means the MR was manually rejected. CloseReasonRejected CloseReason = "rejected" // CloseReasonConflict means the MR had unresolvable conflicts. CloseReasonConflict CloseReason = "conflict" // CloseReasonSuperseded means the MR was replaced by another. CloseReasonSuperseded CloseReason = "superseded" )
type Engineer ¶
type Engineer struct {
// contains filtered or unexported fields
}
Engineer is the merge queue processor that polls for ready merge-requests and processes them according to the merge queue design.
func NewEngineer ¶
NewEngineer creates a new Engineer for the given rig.
func (*Engineer) Config ¶
func (e *Engineer) Config() *MergeQueueConfig
Config returns the current merge queue configuration.
func (*Engineer) IsBeadOpen ¶
IsBeadOpen checks if a bead is still open (not closed). This is used as a status checker for mrqueue.ListReady to filter blocked MRs.
func (*Engineer) ListBlockedMRs ¶
ListBlockedMRs returns MRs that are blocked by open tasks. Useful for monitoring/reporting.
func (*Engineer) ListReadyMRs ¶
ListReadyMRs returns MRs that are ready for processing: - Not claimed by another worker (or claim is stale) - Not blocked by an open task Sorted by priority score (highest first).
func (*Engineer) LoadConfig ¶
LoadConfig loads merge queue configuration from the rig's config.json.
func (*Engineer) ProcessMRFromQueue ¶
ProcessMRFromQueue processes a merge request from wisp queue.
type FailureType ¶
type FailureType string
FailureType categorizes merge failures for appropriate handling.
const ( // FailureNone indicates no failure (success). FailureNone FailureType = "" // FailureConflict indicates merge conflicts with target branch. FailureConflict FailureType = "conflict" // FailureTestsFail indicates tests failed after merge. FailureTestsFail FailureType = "tests_fail" // FailureBuildFail indicates build failed after merge. FailureBuildFail FailureType = "build_fail" // FailureFlakyTest indicates a potentially flaky test failure (may retry). FailureFlakyTest FailureType = "flaky_test" // FailurePushFail indicates push to remote failed. FailurePushFail FailureType = "push_fail" // FailureFetch indicates fetch of source branch failed. FailureFetch FailureType = "fetch_fail" // FailureCheckout indicates checkout of target branch failed. FailureCheckout FailureType = "checkout_fail" )
func (FailureType) FailureLabel ¶
func (f FailureType) FailureLabel() string
FailureLabel returns the beads label for this failure type.
func (FailureType) ShouldAssignToWorker ¶
func (f FailureType) ShouldAssignToWorker() bool
ShouldAssignToWorker returns true if this failure should be assigned back to the worker.
type MRStatus ¶
type MRStatus string
MRStatus represents the status of a merge request. Uses beads-style statuses for consistency with the issue tracking system.
const ( // MROpen means the MR is waiting to be processed or needs rework. MROpen MRStatus = "open" // MRInProgress means the MR is currently being merged by the Engineer. MRInProgress MRStatus = "in_progress" // MRClosed means the MR processing is complete (merged, rejected, etc). MRClosed MRStatus = "closed" )
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager handles refinery lifecycle and queue operations.
func NewManager ¶
NewManager creates a new refinery manager for a rig.
func (*Manager) FindMR ¶
func (m *Manager) FindMR(idOrBranch string) (*MergeRequest, error)
FindMR finds a merge request by ID or branch name in the queue.
func (*Manager) GetMR ¶
func (m *Manager) GetMR(id string) (*MergeRequest, error)
GetMR returns a merge request by ID from the state.
func (*Manager) ProcessMR
deprecated
func (m *Manager) ProcessMR(mr *MergeRequest) MergeResult
ProcessMR is deprecated - the Refinery agent now handles all merge processing.
ZFC #5: Move merge/conflict decisions from Go to Refinery agent
The agent runs git commands directly and makes decisions based on output:
- Agent attempts merge: git checkout -b temp origin/polecat/<worker>
- Agent detects conflict and decides: retry, notify polecat, escalate
- Agent runs tests and decides: proceed, rollback, retry
- Agent pushes: git push origin main
This function is kept for backwards compatibility but always returns an error indicating that the agent should handle merge processing.
Deprecated: Use the Refinery agent (Claude) for merge processing.
func (*Manager) Queue ¶
Queue returns the current merge queue. Uses beads merge-request issues as the source of truth (not git branches).
func (*Manager) RegisterMR ¶
func (m *Manager) RegisterMR(mr *MergeRequest) error
RegisterMR adds a merge request to the pending queue.
func (*Manager) RejectMR ¶
RejectMR manually rejects a merge request. It closes the MR with rejected status and optionally notifies the worker. Returns the rejected MR for display purposes.
func (*Manager) Retry ¶
Retry resets a failed merge request so it can be processed again. The processNow parameter is deprecated - the Refinery agent handles processing. Clearing the error is sufficient; the agent will pick up the MR in its next patrol cycle.
func (*Manager) SessionName ¶
SessionName returns the tmux session name for this refinery.
func (*Manager) SetOutput ¶
SetOutput sets the output writer for user-facing messages. This is useful for testing or redirecting output.
func (*Manager) Start ¶
Start starts the refinery. If foreground is true, runs in the current process (blocking) using the Go-based polling loop. Otherwise, spawns a Claude agent in a tmux session to process the merge queue.
type MergeConfig ¶
type MergeConfig struct {
// RunTests controls whether tests are run after merge.
// Default: true
RunTests bool `json:"run_tests"`
// TestCommand is the command to run for testing.
// Default: "go test ./..."
TestCommand string `json:"test_command"`
// DeleteMergedBranches controls whether merged branches are deleted.
// Default: true
DeleteMergedBranches bool `json:"delete_merged_branches"`
// PushRetryCount is the number of times to retry a failed push.
// Default: 3
PushRetryCount int `json:"push_retry_count"`
// PushRetryDelayMs is the base delay between push retries in milliseconds.
// Each retry doubles the delay (exponential backoff).
// Default: 1000
PushRetryDelayMs int `json:"push_retry_delay_ms"`
}
MergeConfig contains configuration for the merge process.
func DefaultMergeConfig ¶
func DefaultMergeConfig() MergeConfig
DefaultMergeConfig returns the default merge configuration.
type MergeQueueConfig ¶
type MergeQueueConfig struct {
// Enabled controls whether the merge queue is active.
Enabled bool `json:"enabled"`
// TargetBranch is the default branch to merge to (e.g., "main").
TargetBranch string `json:"target_branch"`
// IntegrationBranches enables per-epic integration branches.
IntegrationBranches bool `json:"integration_branches"`
// OnConflict is the strategy for handling conflicts: "assign_back" or "auto_rebase".
OnConflict string `json:"on_conflict"`
// RunTests controls whether to run tests before merging.
RunTests bool `json:"run_tests"`
// TestCommand is the command to run for testing.
TestCommand string `json:"test_command"`
// DeleteMergedBranches controls whether to delete branches after merge.
DeleteMergedBranches bool `json:"delete_merged_branches"`
// RetryFlakyTests is the number of times to retry flaky tests.
RetryFlakyTests int `json:"retry_flaky_tests"`
// PollInterval is how often to check for new MRs.
PollInterval time.Duration `json:"poll_interval"`
// MaxConcurrent is the maximum number of MRs to process concurrently.
MaxConcurrent int `json:"max_concurrent"`
}
MergeQueueConfig holds configuration for the merge queue processor.
func DefaultMergeQueueConfig ¶
func DefaultMergeQueueConfig() *MergeQueueConfig
DefaultMergeQueueConfig returns sensible defaults for merge queue configuration.
type MergeRequest ¶
type MergeRequest struct {
// ID is a unique identifier for this merge request.
ID string `json:"id"`
// Branch is the source branch name (e.g., "polecat/Toast/gt-abc").
Branch string `json:"branch"`
// Worker is the polecat that created this branch.
Worker string `json:"worker"`
// IssueID is the beads issue being worked on.
IssueID string `json:"issue_id"`
// SwarmID is the swarm this work belongs to (if any).
SwarmID string `json:"swarm_id,omitempty"`
// TargetBranch is where this should merge (usually integration or main).
TargetBranch string `json:"target_branch"`
// CreatedAt is when the MR was queued.
CreatedAt time.Time `json:"created_at"`
// Status is the current status of the merge request.
Status MRStatus `json:"status"`
// CloseReason indicates why the MR was closed (only set when Status=closed).
CloseReason CloseReason `json:"close_reason,omitempty"`
// Error contains error details if the MR failed.
Error string `json:"error,omitempty"`
}
MergeRequest represents a branch waiting to be merged.
func (*MergeRequest) Claim ¶
func (mr *MergeRequest) Claim() error
Claim transitions the MR from open to in_progress (Engineer claims it). Returns an error if the transition is not allowed.
func (*MergeRequest) Close ¶
func (mr *MergeRequest) Close(reason CloseReason) error
Close closes the MR with the given reason after validating the transition. Returns an error if the MR cannot be closed from its current state. Once closed, an MR cannot be closed again (even with a different reason).
func (*MergeRequest) IsClosed ¶
func (mr *MergeRequest) IsClosed() bool
IsClosed returns true if the MR is in a closed state.
func (*MergeRequest) IsInProgress ¶
func (mr *MergeRequest) IsInProgress() bool
IsInProgress returns true if the MR is currently being processed.
func (*MergeRequest) IsOpen ¶
func (mr *MergeRequest) IsOpen() bool
IsOpen returns true if the MR is in an open state (waiting for processing).
func (*MergeRequest) Reopen ¶
func (mr *MergeRequest) Reopen() error
Reopen reopens a failed MR (transitions from in_progress back to open). Returns an error if the transition is not allowed.
func (*MergeRequest) SetStatus ¶
func (mr *MergeRequest) SetStatus(newStatus MRStatus) error
SetStatus updates the MR status after validating the transition. Returns an error if the transition is not allowed.
type MergeResult ¶
type MergeResult struct {
Success bool
MergeCommit string // SHA of merge commit on success
Error string
Conflict bool
TestsFailed bool
}
MergeResult contains the result of a merge attempt.
type ProcessResult ¶
type ProcessResult struct {
Success bool
MergeCommit string
Error string
Conflict bool
TestsFailed bool
}
ProcessResult contains the result of processing a merge request.
type QueueItem ¶
type QueueItem struct {
Position int `json:"position"`
MR *MergeRequest `json:"mr"`
Age string `json:"age"`
}
QueueItem represents an item in the merge queue for display.
type Refinery ¶
type Refinery struct {
// RigName is the rig this refinery processes.
RigName string `json:"rig_name"`
// State is the current running state.
State State `json:"state"`
// PID is the process ID if running in background.
PID int `json:"pid,omitempty"`
// StartedAt is when the refinery was started.
StartedAt *time.Time `json:"started_at,omitempty"`
// CurrentMR is the merge request currently being processed.
CurrentMR *MergeRequest `json:"current_mr,omitempty"`
// PendingMRs tracks merge requests that have been submitted.
// Key is the MR ID.
PendingMRs map[string]*MergeRequest `json:"pending_mrs,omitempty"`
// LastMergeAt is when the last successful merge happened.
LastMergeAt *time.Time `json:"last_merge_at,omitempty"`
}
Refinery represents a rig's merge queue processor.