// engine/spec-migrator/fold-progress.ts — SPEC-752
// Handles legacy progress.md: either folds it into spec.md or drops it when it's boilerplate-only.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { atomicWriteFile } from '../safety/atomic-write-file.js';
import { safeUnlink } from './git-aware-fs.js';
/**
 * Detect whether progress.md content is pure auto-generated boilerplate.
 * Heuristic: >70% of non-empty lines start with `- [ ]` AND there is no narrative paragraph
 * (a paragraph is defined as 2+ consecutive non-bullet lines of ≥20 chars).
 */
export function isBoilerplateProgress(content) {
    const lines = content.split('\n').filter((l) => l.trim().length > 0);
    if (lines.length === 0) {
        return true;
    }
    const todoLines = lines.filter((l) => /^\s*-\s*\[\s*[ x]\s*\]/.test(l));
    const todoRatio = todoLines.length / lines.length;
    if (todoRatio <= 0.7) {
        return false;
    }
    // Check for narrative paragraphs: 2+ consecutive non-bullet, non-heading lines of ≥20 chars
    const nonBulletLines = lines.filter((l) => !/^\s*[-*#>]/.test(l) && !l.startsWith('---') && l.trim().length >= 20);
    if (nonBulletLines.length >= 2) {
        return false;
    }
    return true;
}
/**
 * Fold or drop progress.md for a spec directory.
 * When content is boilerplate-only: silently delete progress.md.
 * When content has narrative: append as `## Progress` section in spec.md.
 *
 * @param specDir       Absolute path to the spec directory.
 * @param opts.dropBoilerplate  When true, boilerplate-only progress.md is dropped without folding.
 * @param projectPath   Project root for git-aware unlink (optional).
 */
export async function foldProgressIntoSpec(specDir, opts, projectPath) {
    const specPath = join(specDir, 'spec.md');
    const progressPath = join(specDir, 'progress.md');
    try {
        let progressContent;
        try {
            progressContent = await readFile(progressPath, 'utf-8');
        }
        catch {
            return { ok: true, reason: 'no_progress_md' };
        }
        // Strip frontmatter if present
        const body = progressContent.replace(/^---\n[\s\S]*?\n---\n?/, '').trim();
        const unlink = projectPath
            ? (path) => safeUnlink(projectPath, path)
            : async (path) => {
                const { unlink: fsUnlink } = await import('node:fs/promises');
                await fsUnlink(path);
            };
        if (opts.dropBoilerplate && isBoilerplateProgress(body)) {
            await unlink(progressPath);
            return { ok: true, reason: 'dropped_boilerplate', byteDelta: 0 };
        }
        // Fold into spec.md
        const specContent = await readFile(specPath, 'utf-8');
        const unified = `${specContent.trimEnd()}\n\n## Progress\n\n${body}\n`;
        const before = Buffer.byteLength(specContent, 'utf-8');
        const after = Buffer.byteLength(unified, 'utf-8');
        await atomicWriteFile(specPath, unified);
        await unlink(progressPath);
        return { ok: true, reason: 'ok', byteDelta: after - before };
    }
    catch (err) {
        return { ok: false, reason: 'error', error: String(err) };
    }
}
//# sourceMappingURL=fold-progress.js.map