/**
 * Context truncation — reduces large .planning/ files to cache-friendly sizes.
 *
 * Two strategies:
 * 1. Markdown-aware truncation: keeps headings + first paragraph per section,
 *    replaces the rest with a pointer to the full file.
 * 2. Milestone extraction: pulls only the current milestone from ROADMAP.md.
 *
 * All functions are pure — no I/O, no side effects.
 */
export const DEFAULT_TRUNCATION_OPTIONS = {
    maxContentLength: 8192,
};
// ─── Markdown-aware truncation ──────────────────────────────────────────────
/**
 * Truncate markdown content while preserving structure.
 *
 * Strategy: keep YAML frontmatter, all headings, and the first paragraph under
 * each heading. Collapse everything else with a line count summary.
 *
 * Returns the original content unchanged if below maxContentLength.
 */
export function truncateMarkdown(content, filename, options = DEFAULT_TRUNCATION_OPTIONS) {
    if (content.length <= options.maxContentLength)
        return content;
    const lines = content.split('\n');
    const kept = [];
    let inFrontmatter = false;
    let frontmatterDone = false;
    let currentSectionLines = 0;
    let paragraphKept = false;
    let omittedLines = 0;
    let inParagraph = false;
    for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        // Handle YAML frontmatter (preserve entirely)
        if (i === 0 && line.trim() === '---') {
            inFrontmatter = true;
            kept.push(line);
            continue;
        }
        if (inFrontmatter) {
            kept.push(line);
            if (line.trim() === '---') {
                inFrontmatter = false;
                frontmatterDone = true;
            }
            continue;
        }
        // Heading — always keep, reset paragraph tracking
        if (/^#{1,6}\s/.test(line)) {
            if (omittedLines > 0) {
                kept.push(`[... ${omittedLines} lines omitted]`);
                omittedLines = 0;
            }
            kept.push(line);
            currentSectionLines = 0;
            paragraphKept = false;
            inParagraph = false;
            continue;
        }
        // Empty line — paragraph boundary
        if (line.trim() === '') {
            if (inParagraph && !paragraphKept) {
                // End of first paragraph — mark it kept
                paragraphKept = true;
            }
            if (!paragraphKept || currentSectionLines === 0) {
                kept.push(line);
            }
            else {
                omittedLines++;
            }
            inParagraph = false;
            continue;
        }
        // Content line
        currentSectionLines++;
        if (!paragraphKept) {
            // Still in the first paragraph — keep it
            kept.push(line);
            inParagraph = true;
        }
        else {
            omittedLines++;
        }
    }
    if (omittedLines > 0) {
        kept.push(`[... ${omittedLines} lines omitted]`);
    }
    const totalOmitted = lines.length - kept.length;
    if (totalOmitted > 0) {
        kept.push('');
        kept.push(`[Truncated: read .planning/${filename} for full content]`);
    }
    return kept.join('\n');
}
// ─── Milestone extraction ───────────────────────────────────────────────────
/**
 * Extract the current milestone section from a ROADMAP.md.
 *
 * Parses STATE.md to find the current milestone name, then extracts only
 * that milestone's section from the roadmap. Falls back to full content
 * if the milestone can't be identified or found.
 */
export function extractCurrentMilestone(roadmapContent, stateContent) {
    if (!stateContent)
        return roadmapContent;
    // Find current milestone from STATE.md
    // Patterns: "Current Milestone: X", "milestone: X", "## Current Position" block
    const milestonePatterns = [
        /current\s*milestone\s*:\s*(.+)/i,
        /^milestone\s*:\s*(.+)/im,
        /##\s*current\s*position[\s\S]*?milestone\s*:\s*(.+)/i,
    ];
    let milestoneName;
    for (const pattern of milestonePatterns) {
        const match = stateContent.match(pattern);
        if (match) {
            milestoneName = match[1].trim();
            break;
        }
    }
    if (!milestoneName)
        return roadmapContent;
    // Find the milestone section in roadmap
    // Look for heading containing the milestone name
    const lines = roadmapContent.split('\n');
    let sectionStart = -1;
    let sectionEnd = lines.length;
    let sectionHeadingLevel = 0;
    for (let i = 0; i < lines.length; i++) {
        const headingMatch = lines[i].match(/^(#{1,6})\s+(.+)/);
        if (!headingMatch)
            continue;
        const level = headingMatch[1].length;
        const title = headingMatch[2];
        if (sectionStart === -1) {
            // Looking for the milestone heading
            if (title.toLowerCase().includes(milestoneName.toLowerCase())) {
                sectionStart = i;
                sectionHeadingLevel = level;
            }
        }
        else {
            // Found start — look for next heading at same or higher level
            if (level <= sectionHeadingLevel) {
                sectionEnd = i;
                break;
            }
        }
    }
    if (sectionStart === -1)
        return roadmapContent;
    // Extract preamble (everything before first milestone heading at the same level)
    const preamble = [];
    for (let i = 0; i < lines.length; i++) {
        const headingMatch = lines[i].match(/^(#{1,6})\s/);
        if (headingMatch && headingMatch[1].length === sectionHeadingLevel && i !== sectionStart) {
            // Hit another milestone-level heading before our section
            if (i < sectionStart) {
                break; // preamble ends at first milestone heading
            }
        }
        if (i < sectionStart) {
            // Keep top-level title and intro
            if (i === 0 || lines[i].match(/^#\s/) || !lines[i].match(/^#{1,6}\s/)) {
                preamble.push(lines[i]);
            }
        }
    }
    const milestoneSection = lines.slice(sectionStart, sectionEnd).join('\n');
    const otherMilestones = countOtherMilestones(lines, sectionHeadingLevel, sectionStart);
    const result = [
        ...preamble,
        '',
        milestoneSection,
    ];
    if (otherMilestones > 0) {
        result.push('');
        result.push(`[${otherMilestones} other milestone(s) omitted — read .planning/ROADMAP.md for full roadmap]`);
    }
    return result.join('\n').trim();
}
function countOtherMilestones(lines, headingLevel, excludeIndex) {
    let count = 0;
    for (let i = 0; i < lines.length; i++) {
        if (i === excludeIndex)
            continue;
        const match = lines[i].match(/^(#{1,6})\s/);
        if (match && match[1].length === headingLevel) {
            count++;
        }
    }
    return count;
}
//# sourceMappingURL=context-truncation.js.map