/**
 * Expert Orchestrator
 *
 * Picks an ordered sequence of expert droids for a given task, using the
 * existing CapabilityRouter for the primary match plus a canonical lifecycle
 * sequence (plan → architect → implement → review → release) to layer
 * appropriate experts at each phase.
 *
 * Persists per-droid success rates by reusing the AdaptivePatternStore
 * abstraction so the chain composition improves over time.
 */
import { CapabilityRouter } from './capability-router.js';
const DEFAULT_PHASES = ['plan', 'design', 'implement', 'review', 'release'];
/**
 * Per-phase canonical droids. The orchestrator picks from these in addition
 * to whatever the CapabilityRouter recommends based on task content.
 */
const PHASE_ROSTER = {
    // Divergent ideation (open-collider) — opt-in via includeIdeation. Its curated
    // ideas feed the plan-phase product/strategy droids.
    ideate: { droids: ['ideation-expert'], parallel: false },
    // strategic-architect sets the north-star direction alongside product/test strategy.
    plan: { droids: ['product-strategist', 'test-strategist', 'strategic-architect'], parallel: true },
    // tactical-architect designs the concrete components; implementation-planner turns
    // the design into an executable work breakdown before code starts.
    design: {
        droids: ['architect-reviewer', 'api-designer', 'tactical-architect', 'implementation-planner'],
        parallel: true,
    },
    // implement phase gets its droids exclusively from the capability router,
    // because language/domain choice depends on the actual files touched.
    implement: { droids: [], parallel: false },
    review: {
        droids: [
            'code-quality-reviewer',
            'security-code-reviewer',
            'performance-reviewer',
            'documentation-accuracy-reviewer',
            'test-coverage-reviewer',
        ],
        parallel: true,
    },
    release: { droids: ['release-manager'], parallel: false },
};
/**
 * Decides which roster droids are *relevant* given the capability router's
 * matched capabilities. Avoids fanning out experts that have no business
 * with this task (e.g., no api-designer if no API surface changed).
 */
function isRelevantForCapability(droid, matched) {
    // Always-relevant defaults — these run regardless of capability match.
    const alwaysOn = new Set(['code-quality-reviewer', 'release-manager']);
    if (alwaysOn.has(droid))
        return true;
    const map = {
        'product-strategist': ['product'],
        'test-strategist': ['testing', 'test-strategy'],
        'strategic-architect': ['architecture'],
        'tactical-architect': ['architecture', 'api-design'],
        'implementation-planner': ['architecture', 'api-design', 'testing', 'product'],
        'architect-reviewer': ['architecture'],
        'api-designer': ['api-design'],
        'security-code-reviewer': ['security'],
        'performance-reviewer': ['performance'],
        'documentation-accuracy-reviewer': ['documentation'],
        'test-coverage-reviewer': ['testing'],
    };
    const relevantCapabilities = map[droid];
    if (!relevantCapabilities)
        return true;
    return relevantCapabilities.some((c) => matched.includes(c));
}
/**
 * Orchestrator entry point. Stateless — instantiating is cheap; persistence
 * for adaptive metrics is delegated to the injected `successRateFor`.
 */
export class ExpertOrchestrator {
    router;
    phases;
    successRateFor;
    constructor(options = {}) {
        this.router = options.router ?? new CapabilityRouter();
        this.phases =
            options.phases ?? (options.includeIdeation ? ['ideate', ...DEFAULT_PHASES] : DEFAULT_PHASES);
        this.successRateFor = options.successRateFor ?? (() => null);
    }
    /**
     * Build a recommended chain for the given task. Task content drives the
     * capability match; the phase roster fills out the lifecycle layers.
     */
    plan(task, affectedFiles) {
        const capability = this.router.routeTask(task, affectedFiles);
        const matched = capability.matchedCapabilities;
        const steps = [];
        for (const phase of this.phases) {
            if (phase === 'implement') {
                // Pull from capability router's recommendations
                for (const droid of capability.recommendedDroids) {
                    steps.push({
                        phase,
                        droid,
                        rationale: `Capability match: ${capability.reasoning}`.slice(0, 240),
                        parallel: false,
                        successRate: this.successRateFor(droid),
                    });
                }
                continue;
            }
            const roster = PHASE_ROSTER[phase];
            for (const droid of roster.droids) {
                if (!isRelevantForCapability(droid, matched))
                    continue;
                steps.push({
                    phase,
                    droid,
                    rationale: `${phase} roster (matched ${matched.join(', ') || 'baseline'})`,
                    parallel: roster.parallel,
                    successRate: this.successRateFor(droid),
                });
            }
        }
        return {
            task: task.title ?? task.description ?? '',
            capability,
            steps,
            confidence: capability.confidence,
        };
    }
}
/**
 * Convenience for callers that have a free-form task description rather than
 * a full `Task`. Wraps the string in a minimal Task shape.
 */
export function planFromDescription(description, orchestrator, affectedFiles) {
    const orch = orchestrator ?? new ExpertOrchestrator();
    const now = new Date().toISOString();
    const task = {
        id: 'adhoc',
        title: description.slice(0, 80) || 'adhoc',
        description,
        type: 'task',
        status: 'open',
        priority: 2,
        labels: [],
        createdAt: now,
        updatedAt: now,
    };
    return orch.plan(task, affectedFiles);
}
//# sourceMappingURL=expert-orchestrator.js.map