// engine/autopilot/complete-loop.ts — SPEC-569: Complete-loop autopilot helpers.
// Wires up auto-branch, auto-TDD, and auto-PR fire-and-forget side effects for
// update_status transitions and emits `autopilot:action` progress events.
//
// Rules:
//   * Every action is fire-and-forget — caller never awaits these helpers.
//   * Errors MUST be swallowed (logged only) so they never surface in update_status responses.
//   * Progress is observable via the event-bus (`autopilot:action`).
import { emitAutopilotEvent } from './event-bus.js';
/** SPEC-569: Default minimum validate score required to auto-create a PR. */
export const DEFAULT_AUTO_MERGE_THRESHOLD = 85;
/** Emit a progress event on the shared event-bus (fire-and-forget). */
function emitProgress(projectPath, projectId, specId, action, status, extra) {
    emitAutopilotEvent({
        name: 'autopilot:action',
        specId,
        projectPath,
        projectId,
        payload: {
            action,
            specId,
            status,
            ...(extra ?? {}),
        },
    });
}
/** Shared wrapper: emits started/completed/failed around a thunk. */
async function runWithProgress(projectPath, projectId, specId, action, fn) {
    emitProgress(projectPath, projectId, specId, action, 'started');
    try {
        const summary = await fn();
        emitProgress(projectPath, projectId, specId, action, 'completed', { summary });
    }
    catch (err) {
        /* v8 ignore next */
        const message = err instanceof Error ? err.message : String(err);
        emitProgress(projectPath, projectId, specId, action, 'failed', { error: message });
        console.error(`[autopilot:${action}] ${specId} failed: ${message}`);
    }
}
// ---------------------------------------------------------------------------
// autoCreateBranch
// ---------------------------------------------------------------------------
/**
 * SPEC-569: Auto-create a feature branch for the spec. Delegates to the
 * existing create-branch handler so naming conventions stay consistent.
 */
async function doAutoCreateBranch(projectId, specId) {
    const { handleCreateBranch } = await import('../../tools/git/branch-ops.js');
    const result = await handleCreateBranch(projectId, specId);
    if (result.isError === true) {
        /* v8 ignore next */
        const msg = result.content[0]?.type === 'text' ? result.content[0].text : 'branch creation failed';
        throw new Error(msg);
    }
    return 'branch created';
}
export function fireAutoCreateBranch(projectPath, projectId, specId) {
    void runWithProgress(projectPath, projectId, specId, 'autoCreateBranch', () => doAutoCreateBranch(projectId, specId));
}
// ---------------------------------------------------------------------------
// autoScaffoldTdd
// ---------------------------------------------------------------------------
/**
 * SPEC-569: Auto-generate TDD scaffolding for the spec. Delegates to the
 * tdd_scaffold handler once the spec path is resolved.
 */
async function doAutoScaffoldTdd(projectPath, projectId, specId) {
    const { specStore } = await import('../../storage/index.js');
    const spec = await specStore.getSpec(projectId, specId);
    if (!spec?.specPath) {
        throw new Error(`spec ${specId} has no specPath`);
    }
    const { handleTddScaffold } = await import('../../tools/tdd-scaffold-handler.js');
    const result = await handleTddScaffold({ projectPath, specPath: spec.specPath });
    if (result.isError === true) {
        /* v8 ignore next */
        const msg = result.content[0]?.type === 'text' ? result.content[0].text : 'tdd scaffold failed';
        throw new Error(msg);
    }
    return 'tdd scaffold generated';
}
export function fireAutoScaffoldTdd(projectPath, projectId, specId) {
    void runWithProgress(projectPath, projectId, specId, 'autoScaffoldTdd', () => doAutoScaffoldTdd(projectPath, projectId, specId));
}
// ---------------------------------------------------------------------------
// autoCreatePr
// ---------------------------------------------------------------------------
/** Resolve threshold: explicit config value, else the default. */
export function resolveAutoMergeThreshold(config) {
    return typeof config.autoMergeThreshold === 'number'
        ? config.autoMergeThreshold
        : DEFAULT_AUTO_MERGE_THRESHOLD;
}
/**
 * SPEC-569: Auto-create a PR if validate score passes the configured threshold.
 * Fire-and-forget — delegates to handleCreatePRFromSpec and captures errors.
 */
async function doAutoCreatePr(specId) {
    const { handleCreatePRFromSpec } = await import('../../tools/github-pr-handler.js');
    const result = await handleCreatePRFromSpec({
        specId,
        baseBranch: 'develop',
        draft: false,
    });
    if (result.isError === true) {
        /* v8 ignore next */
        const msg = result.content[0]?.type === 'text' ? result.content[0].text : 'pr creation failed';
        throw new Error(msg);
    }
    return 'pr created';
}
/**
 * SPEC-569: Fire-and-forget PR creation gated on validateScore >= threshold.
 * If the threshold is not met, emits a `failed` progress event with the reason
 * so observers can surface the miss to the user without blocking the main flow.
 */
export function fireAutoCreatePr(projectPath, projectId, specId, validateScore, threshold) {
    if (validateScore === null || validateScore < threshold) {
        emitProgress(projectPath, projectId, specId, 'autoCreatePr', 'failed', {
            error: `score ${String(validateScore)} below threshold ${String(threshold)}`,
            threshold,
            validateScore,
        });
        return;
    }
    void runWithProgress(projectPath, projectId, specId, 'autoCreatePr', () => doAutoCreatePr(specId));
}
// ---------------------------------------------------------------------------
// Dispatcher — called from update-status side-effects.
// ---------------------------------------------------------------------------
/**
 * SPEC-569: Fire the configured complete-loop actions for a status transition.
 *
 * - `approved`  → autoCreateBranch + autoScaffoldTdd (both gated by config flags)
 * - `done`      → autoCreatePr (gated by flag AND score threshold)
 *
 * This function never throws. All work is fire-and-forget.
 */
export function fireCompleteLoopActions(params) {
    const { projectPath, projectId, specId, newStatus, validateScore, config } = params;
    if (newStatus === 'approved') {
        if (config.autoCreateBranch === true) {
            fireAutoCreateBranch(projectPath, projectId, specId);
        }
        if (config.autoScaffoldTdd === true) {
            fireAutoScaffoldTdd(projectPath, projectId, specId);
        }
        return;
    }
    if (newStatus === 'done' && config.autoCreatePr === true) {
        fireAutoCreatePr(projectPath, projectId, specId, validateScore, resolveAutoMergeThreshold(config));
    }
}
//# sourceMappingURL=complete-loop.js.map