/**
 * Merge Steward Service
 *
 * This service implements the auto-merge functionality for the orchestration system.
 * The Merge Steward detects completed tasks and merges their branches.
 *
 * Key features:
 * - Detect tasks with mergeStatus 'pending'
 * - Run tests on the task's branch
 * - Auto-merge if tests pass
 * - Create fix tasks if tests fail
 * - Handle merge conflicts
 * - Clean up worktrees after successful merge
 *
 * TB-O21: Merge Steward Auto-Merge
 *
 * @module
 */
import type { Task, ElementId, EntityId, Timestamp } from '@stoneforge/core';
import type { QuarryAPI } from '@stoneforge/quarry';
import type { MergeStatus, TestResult } from '../types/index.js';
import type { TaskAssignmentService, TaskAssignment } from './task-assignment-service.js';
import type { DispatchService } from './dispatch-service.js';
import type { WorktreeManager } from '../git/worktree-manager.js';
import type { AgentRegistry } from './agent-registry.js';
import type { OperationLogService } from './operation-log-service.js';
/**
 * Error thrown when an optimistic locking conflict is detected during
 * a merge status transition. This indicates another steward instance
 * has already claimed the task.
 */
export declare class MergeStatusConflictError extends Error {
    readonly expectedStatus: MergeStatus;
    readonly actualStatus: MergeStatus | undefined;
    readonly taskId: string;
    constructor(taskId: string, expectedStatus: MergeStatus, actualStatus: MergeStatus | undefined);
}
/**
 * Merge strategy for combining branches
 */
export type MergeStrategy = 'squash' | 'merge';
/**
 * Configuration for the Merge Steward service
 */
export interface MergeStewardConfig {
    /** Workspace root directory (where git repo is) */
    readonly workspaceRoot: string;
    /** Test command to run (defaults to 'npm test') */
    readonly testCommand?: string;
    /** Timeout for test execution in ms (defaults to 5 minutes) */
    readonly testTimeoutMs?: number;
    /** Whether to auto-merge when tests pass (defaults to true) */
    readonly autoMerge?: boolean;
    /** Whether to auto-cleanup worktree after merge (defaults to true) */
    readonly autoCleanup?: boolean;
    /** Whether to delete branch after merge (defaults to true) */
    readonly deleteBranchAfterMerge?: boolean;
    /** Default branch to merge into (defaults to auto-detect) */
    readonly targetBranch?: string;
    /** Entity ID of the steward for creating tasks */
    readonly stewardEntityId?: EntityId;
    /** Merge strategy: 'squash' (default) or 'merge' */
    readonly mergeStrategy?: MergeStrategy;
    /** Whether to auto-push to remote after successful merge (defaults to true) */
    readonly autoPushAfterMerge?: boolean;
}
/**
 * Options for processing a task for merge
 */
export interface ProcessTaskOptions {
    /** Skip test execution */
    skipTests?: boolean;
    /** Force merge even if there are minor issues */
    forceMerge?: boolean;
    /** Custom commit message for the merge */
    mergeCommitMessage?: string;
    /** Entity performing the operation */
    performedBy?: EntityId;
}
/**
 * Result of processing a task for merge
 */
export interface MergeProcessResult {
    /** The task ID */
    taskId: ElementId;
    /** The final merge status. 'skipped' indicates another steward already claimed the task. */
    status: MergeStatus | 'skipped';
    /** Whether the task was successfully merged */
    merged: boolean;
    /** Test result if tests were run */
    testResult?: TestResult;
    /** Merge commit hash if merged */
    mergeCommitHash?: string;
    /** If a fix task was created, its ID */
    fixTaskId?: ElementId;
    /** Error message if processing failed */
    error?: string;
    /** Timestamp when processing completed */
    processedAt: Timestamp;
}
/**
 * Result of running tests on a branch
 */
export interface TestRunResult {
    /** Whether tests passed */
    passed: boolean;
    /** Full test output */
    output: string;
    /** Exit code from test command */
    exitCode: number;
    /** Duration of test run in ms */
    durationMs: number;
    /** Parsed test result if available */
    testResult: TestResult;
}
/**
 * Result of attempting a merge
 */
export interface MergeAttemptResult {
    /** Whether merge succeeded */
    success: boolean;
    /** Merge commit hash if successful */
    commitHash?: string;
    /** Whether there was a conflict */
    hasConflict: boolean;
    /** Error message if merge failed */
    error?: string;
    /** Files with conflicts if any */
    conflictFiles?: string[];
    /** Whether the source branch was already fully merged (zero commits ahead) */
    alreadyMerged?: boolean;
}
/**
 * Options for creating a fix task
 */
export interface CreateFixTaskOptions {
    /** Type of fix needed */
    type: 'test_failure' | 'merge_conflict' | 'general';
    /** Error message or details about what needs fixing */
    errorDetails: string;
    /** File paths involved (for conflicts) */
    affectedFiles?: string[];
}
/**
 * Batch processing result
 */
export interface BatchProcessResult {
    /** Total tasks processed */
    totalProcessed: number;
    /** Tasks successfully merged */
    mergedCount: number;
    /** Tasks where tests failed */
    testFailedCount: number;
    /** Tasks with merge conflicts */
    conflictCount: number;
    /** Tasks that failed for other reasons */
    errorCount: number;
    /** Individual results */
    results: MergeProcessResult[];
    /** Processing duration in ms */
    durationMs: number;
}
/**
 * Merge Steward Service interface for auto-merging completed task branches.
 *
 * The service provides methods for:
 * - Detecting tasks awaiting merge
 * - Running tests on branches
 * - Merging branches to main
 * - Creating fix tasks when tests fail
 * - Cleaning up worktrees after merge
 */
export interface MergeStewardService {
    /**
     * Gets all tasks that are ready for merge processing.
     *
     * This returns tasks with mergeStatus 'pending' (completed, awaiting merge).
     *
     * @returns Array of tasks awaiting merge
     */
    getTasksAwaitingMerge(): Promise<TaskAssignment[]>;
    /**
     * Processes a single task for merge.
     *
     * This method:
     * 1. Runs tests on the task's branch
     * 2. If tests pass, merges the branch
     * 3. If tests fail, creates a fix task
     * 4. Updates task metadata with result
     * 5. Cleans up worktree if successful
     *
     * @param taskId - The task to process
     * @param options - Processing options
     * @returns The processing result
     */
    processTask(taskId: ElementId, options?: ProcessTaskOptions): Promise<MergeProcessResult>;
    /**
     * Processes all tasks awaiting merge.
     *
     * @param options - Processing options
     * @returns Batch processing result
     */
    processAllPending(options?: ProcessTaskOptions): Promise<BatchProcessResult>;
    /**
     * Runs tests on a task's branch.
     *
     * @param taskId - The task whose branch to test
     * @returns Test run result
     */
    runTests(taskId: ElementId): Promise<TestRunResult>;
    /**
     * Attempts to merge a task's branch to main.
     *
     * @param taskId - The task whose branch to merge
     * @param commitMessage - Custom merge commit message
     * @returns Merge attempt result
     */
    attemptMerge(taskId: ElementId, commitMessage?: string): Promise<MergeAttemptResult>;
    /**
     * Creates a fix task for a failed merge or test.
     *
     * @param originalTaskId - The original task that failed
     * @param options - Fix task options
     * @returns The created fix task ID
     */
    createFixTask(originalTaskId: ElementId, options: CreateFixTaskOptions): Promise<ElementId>;
    /**
     * Cleans up a task's worktree after successful merge.
     *
     * @param taskId - The task to clean up
     * @param deleteBranch - Whether to delete the branch
     * @returns Success status
     */
    cleanupAfterMerge(taskId: ElementId, deleteBranch?: boolean): Promise<boolean>;
    /**
     * Updates the merge status of a task.
     *
     * When `expectedCurrentStatus` is provided, the method performs an optimistic
     * locking check: it reads the current mergeStatus and throws a
     * `MergeStatusConflictError` if it doesn't match the expected value. This
     * prevents concurrent steward instances from racing through the same
     * status transition.
     *
     * @param taskId - The task to update
     * @param status - The new merge status
     * @param details - Optional details (e.g., failure reason)
     * @param expectedCurrentStatus - If provided, the current mergeStatus must match this value
     * @returns The updated task
     * @throws {MergeStatusConflictError} If expectedCurrentStatus doesn't match actual status
     */
    updateMergeStatus(taskId: ElementId, status: MergeStatus, details?: {
        failureReason?: string;
        testResult?: TestResult;
    }, expectedCurrentStatus?: MergeStatus): Promise<Task>;
}
/**
 * Implementation of the Merge Steward Service.
 */
export declare class MergeStewardServiceImpl implements MergeStewardService {
    private readonly api;
    private readonly config;
    private readonly taskAssignment;
    private readonly dispatchService;
    private readonly worktreeManager;
    private readonly agentRegistry;
    private readonly operationLog;
    private targetBranch;
    constructor(api: QuarryAPI, taskAssignment: TaskAssignmentService, dispatchService: DispatchService, agentRegistry: AgentRegistry, config: MergeStewardConfig, worktreeManager?: WorktreeManager, operationLog?: OperationLogService);
    getTasksAwaitingMerge(): Promise<TaskAssignment[]>;
    processTask(taskId: ElementId, options?: ProcessTaskOptions): Promise<MergeProcessResult>;
    processAllPending(options?: ProcessTaskOptions): Promise<BatchProcessResult>;
    runTests(taskId: ElementId): Promise<TestRunResult>;
    attemptMerge(taskId: ElementId, commitMessage?: string): Promise<MergeAttemptResult>;
    createFixTask(originalTaskId: ElementId, options: CreateFixTaskOptions): Promise<ElementId>;
    cleanupAfterMerge(taskId: ElementId, deleteBranch?: boolean): Promise<boolean>;
    updateMergeStatus(taskId: ElementId, status: MergeStatus, details?: {
        failureReason?: string;
        testResult?: TestResult;
    }, expectedCurrentStatus?: MergeStatus): Promise<Task>;
    /**
     * Finds existing fix tasks for a given original task and fix type.
     * This prevents creating duplicate fix tasks when tests fail repeatedly.
     */
    private findExistingFixTasks;
    /**
     * Checks whether a branch has any commits ahead of the target branch.
     * Returns true if there are commits to merge, false if the branch is
     * already fully merged (zero commits ahead).
     */
    private branchHasCommitsAhead;
    private getTargetBranch;
}
/**
 * Creates a MergeStewardService instance
 */
export declare function createMergeStewardService(api: QuarryAPI, taskAssignment: TaskAssignmentService, dispatchService: DispatchService, agentRegistry: AgentRegistry, config: MergeStewardConfig, worktreeManager?: WorktreeManager, operationLog?: OperationLogService): MergeStewardService;
//# sourceMappingURL=merge-steward-service.d.ts.map