// engine/release-pipeline/parse-spec-refs.ts — SPEC-1012
// Pure parser: extracts SPEC-NNN IDs from commit messages.
/**
 * Replace fenced code blocks (```...```) and inline code (`...`) with
 * same-length space strings so that SPEC references inside code are ignored.
 * Preserving offsets means we can run the regex on the masked string and
 * then report indices that map 1-to-1 with the original.
 */
function maskCodeSpans(message) {
    // Walk line-by-line and toggle fence state. Handles unclosed fences
    // (common in CI-generated release messages with truncated logs) by
    // masking everything from the last opener through end-of-message.
    const lines = message.split('\n');
    let inFence = false;
    const masked = [];
    for (const line of lines) {
        if (/^\s*```/.test(line)) {
            inFence = !inFence;
            masked.push(' '.repeat(line.length));
            continue;
        }
        masked.push(inFence ? ' '.repeat(line.length) : line);
    }
    // Inline code spans run on the already-masked-fences output so we
    // never double-mask, and `...` inside a fence is already wiped.
    return masked.join('\n').replace(/`[^`\n]*`/g, (m) => ' '.repeat(m.length));
}
/**
 * Extract deduplicated, uppercased SPEC-NNN IDs from a commit message.
 *
 * Handles:
 *   - Plain: `SPEC-1007`
 *   - Bracketed: `[SPEC-100]`
 *   - Parenthesized (conventional commit scope): `feat(SPEC-50): ...`
 *   - Comma-separated: `closes SPEC-1, SPEC-2`
 *   - Case-insensitive: `spec-100`
 *   - Ignores IDs inside fenced (```...```) or inline (`...`) code spans
 */
export function parseSpecIdsFromCommitMessage(message) {
    if (!message.trim()) {
        return [];
    }
    const masked = maskCodeSpans(message);
    // Match SPEC-NNN not preceded or followed by a word character or backtick
    const SPEC_RE = /(?<![`\w])SPEC-(\d+)(?![`\w])/gi;
    const seen = new Set();
    const results = [];
    let m;
    while ((m = SPEC_RE.exec(masked)) !== null) {
        const id = `SPEC-${m[1] ?? ''}`.toUpperCase();
        if (!seen.has(id)) {
            seen.add(id);
            results.push(id);
        }
    }
    return results;
}
//# sourceMappingURL=parse-spec-refs.js.map