import { specStore } from '../storage/index.js';
import { decomposeSpec } from '../engine/spec-decomposer/index.js';
import { jsonResult, errText } from './response-helpers.js';
import { resolveProjectId, missingProjectIdError } from './resolve-project-id.js';
import { calculateTokenBudget, formatBudgetTag } from '../engine/token-budget/index.js';
import { assignModelToSubtask, formatSubtaskCost, } from '../engine/model-router/subtask-model-assigner.js';
// ---------------------------------------------------------------------------
// Handler
// ---------------------------------------------------------------------------
/**
 * Handle the decompose_spec tool call.
 * Resolves spec file paths via specStore, then delegates to the engine.
 */
export async function handleDecomposeSpec(params) {
    const { specId, maxTasks = 5 } = params;
    const projectId = resolveProjectId(params);
    if (!projectId) {
        return missingProjectIdError;
    }
    if (!specId || specId.trim().length === 0) {
        return errText('specId is required. Provide a spec ID such as "SPEC-042".');
    }
    if (maxTasks < 1 || maxTasks > 20) {
        return errText('maxTasks must be between 1 and 20.');
    }
    const spec = await specStore.getSpec(projectId, specId);
    if (!spec) {
        return errText(`Spec '${specId}' not found in project '${projectId}'. ` +
            `Use list_specs to see available spec IDs.`);
    }
    const result = await decomposeSpec(spec.specPath, spec.technicalPath, specId, maxTasks);
    // SPEC-621: Re-assign recommendedModel using the subtask model assigner (keyword + signal rules)
    // and annotate each task with estimatedCost at that model tier.
    const enrichedTasks = result.tasks.map((task) => {
        const model = assignModelToSubtask({ title: task.title });
        return {
            ...task,
            recommendedModel: model,
            estimatedCost: formatSubtaskCost(model),
        };
    });
    // SPEC-620: Inject token budget based on spec devHours (defaults to standard if unknown)
    const specDevHours = spec.estimation.devHours;
    const decomposeBudget = calculateTokenBudget(specDevHours > 0 ? specDevHours : 6, 'write');
    const budgetTag = formatBudgetTag(decomposeBudget);
    return jsonResult({
        ...result,
        tasks: enrichedTasks,
        nextSteps: buildNextSteps(result.orchestrationReady, result.tasks.length),
        tokenBudget: { budget: decomposeBudget, tag: budgetTag },
    });
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function buildNextSteps(orchestrationReady, taskCount) {
    if (!orchestrationReady) {
        return [
            'Review the warnings above — some tasks have no owned files.',
            'Add file paths to the inline ## Files section in spec.md, then re-run decompose_spec.',
        ];
    }
    return [
        `Feed the ${String(taskCount)} tasks into orchestrate_runtime with topology "mesh" for parallel execution.`,
        'Use generate_teammate_prompt to create per-agent prompts from each task.',
        'Run validate_team_results after all agents complete to check for regressions.',
    ];
}
//# sourceMappingURL=decompose-spec.js.map