// tools/flag-spec-gap.ts — SPEC-739: flag_spec_gap tool handler
// Records a spec implementation gap with severity classification and hash-chained persistence.
import { specStore } from '../storage/index.js';
import { appendGapEntry } from '../storage/gaps-log.js';
const SPEC_ID_RE = /^SPEC-\d{3,4}$/;
const VALID_SEVERITIES = ['low', 'medium', 'high'];
/**
 * Handle the flag_spec_gap tool invocation.
 *
 * Validates inputs (severity enum, affectedSpecs pattern + existence),
 * applies defaults, and appends a hash-chained entry to external Planu project data.
 */
export async function handleFlagSpecGap(input) {
    const { projectId, specId, description } = input;
    const severity = input.severity ?? 'medium';
    const affectedSpecs = input.affectedSpecs && input.affectedSpecs.length > 0 ? input.affectedSpecs : [specId];
    // ── Validate severity ─────────────────────────────────────────────────────
    if (!VALID_SEVERITIES.includes(severity)) {
        return {
            content: [
                {
                    type: 'text',
                    text: JSON.stringify({
                        error: 'invalid_input',
                        code: 422,
                        field: 'severity',
                        fixHint: `severity must be one of: ${VALID_SEVERITIES.join(', ')}`,
                    }),
                },
            ],
            isError: true,
        };
    }
    // ── Validate affectedSpecs format ─────────────────────────────────────────
    for (const id of affectedSpecs) {
        if (!SPEC_ID_RE.test(id)) {
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            error: 'invalid_affected_spec',
                            code: 422,
                            fixHint: `${id} does not match the required format SPEC-NNN or SPEC-NNNN`,
                        }),
                    },
                ],
                isError: true,
            };
        }
    }
    // ── Validate affectedSpecs existence ──────────────────────────────────────
    const allSpecs = await specStore.listSpecs(projectId);
    const specIds = new Set(allSpecs.map((s) => s.id));
    for (const id of affectedSpecs) {
        if (!specIds.has(id)) {
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            error: 'invalid_affected_spec',
                            code: 422,
                            fixHint: `${id} not found in project ${projectId}`,
                        }),
                    },
                ],
                isError: true,
            };
        }
    }
    // ── Persist hash-chained entry ────────────────────────────────────────────
    const entry = await appendGapEntry({
        projectId,
        specId,
        description,
        severity,
        affectedSpecs,
    });
    return {
        content: [
            {
                type: 'text',
                text: JSON.stringify({
                    ok: true,
                    id: entry.id,
                    specId: entry.specId,
                    description: entry.description,
                    severity: entry.severity,
                    affectedSpecs: entry.affectedSpecs,
                    timestamp: entry.timestamp,
                    sha: entry.sha,
                    defaults: {
                        severity: input.severity === undefined ? 'medium (default)' : undefined,
                        affectedSpecs: !input.affectedSpecs || input.affectedSpecs.length === 0
                            ? `[${specId}] (default)`
                            : undefined,
                    },
                }),
            },
        ],
        isError: false,
    };
}
//# sourceMappingURL=flag-spec-gap.js.map