// engine/steering/steering-generator.ts — SPEC-434: Steering File Generator
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
const ALL_TARGETS = ['kiro', 'cursor', 'claude', 'cline', 'copilot', 'codex'];
/** Build the Architecture steering section from project context. */
export function buildArchitectureSection(context) {
    const stackLine = context.stack !== undefined && context.stack.length > 0
        ? context.stack.join(', ')
        : 'Not detected';
    const conventionsList = context.conventions !== undefined && context.conventions.length > 0
        ? context.conventions.map((c) => `- ${c}`).join('\n')
        : '- Follow existing code patterns';
    const content = `## Stack
${stackLine}

## Conventions
${conventionsList}

## Spec-Driven Development
This project uses Planu for Spec Driven Development.
- All features have specs in \`planu/specs/\`
- Total specs: ${context.specCount ?? 0}
- Before implementing any feature, check \`list_specs\` for an existing spec
- After implementing, run \`validate\` to verify compliance`;
    return {
        title: 'Architecture',
        content,
        filePath: '.kiro/steering/architecture.md',
    };
}
/** Build the Testing steering section from project context. */
export function buildTestingSection(context) {
    const framework = context.testFramework ?? 'the project test framework';
    const content = `## Test Framework
${framework}

## Test File Location
Test files mirror the source structure (e.g. \`src/engine/foo.ts\` → \`tests/engine/foo.test.ts\`).

## Coverage
Aim for >95% coverage on all modules. Coverage is enforced in CI.

## TDD Recommendation
Write tests before implementation for complex business logic. For simple I/O handlers, implementing first is acceptable.`;
    return {
        title: 'Testing',
        content,
        filePath: '.kiro/steering/testing.md',
    };
}
/** Build a generic Security steering section. */
export function buildSecuritySection() {
    const content = `- Never hardcode credentials or API keys
- Validate all user input at system boundaries
- Use environment variables for secrets
- Sanitize outputs to prevent XSS
- Apply least-privilege principle`;
    return {
        title: 'Security',
        content,
        filePath: '.kiro/steering/security.md',
    };
}
/** Build a generic API design steering section. */
export function buildApiSection() {
    const content = `- RESTful conventions (GET/POST/PUT/DELETE/PATCH semantics)
- Always return consistent error shapes
- Version APIs when breaking changes needed
- Document request/response with TypeScript types`;
    return {
        title: 'API Design',
        content,
    };
}
/** Generate steering content string for a given target and sections. */
export function generateSteeringContent(sections, target) {
    if (target === 'kiro') {
        // For kiro, this function generates content for ONE section at a time
        const section = sections[0];
        if (section === undefined) {
            return '';
        }
        return `# ${section.title}\n\n${section.content}\n\n---\n*Generated by Planu — run \`generate_steering_file\` to update*`;
    }
    if (target === 'claude') {
        const combined = sections.map((s) => `## ${s.title}\n\n${s.content}`).join('\n\n');
        return `<!-- PLANU:STEERING:START -->\n## Project Context (Planu Steering)\n\n${combined}\n<!-- PLANU:STEERING:END -->`;
    }
    if (target === 'cursor') {
        const combined = sections.map((s) => `## ${s.title}\n\n${s.content}`).join('\n\n---\n\n');
        return `# Project Rules\n\n${combined}\n\n---\n*Generated by Planu*`;
    }
    if (target === 'cline') {
        // Same as cursor but with .clinerules header comment
        const combined = sections.map((s) => `## ${s.title}\n\n${s.content}`).join('\n\n---\n\n');
        return `# Project Rules\n\n${combined}\n\n---\n*Generated by Planu*`;
    }
    if (target === 'copilot') {
        const combined = sections.map((s) => `## ${s.title}\n\n${s.content}`).join('\n\n---\n\n');
        return `# GitHub Copilot Instructions\n\n${combined}\n\n---\n*Generated by Planu*`;
    }
    if (target === 'codex') {
        const combined = sections.map((s) => `## ${s.title}\n\n${s.content}`).join('\n\n');
        return `# AGENTS.md — Planu SDD Workflow\n\n${combined}\n\n---\n*Generated by Planu*\n`;
    }
    return '';
}
/** Generate all SteeringFile objects for the given targets. */
export function generateSteeringFiles(context, targets) {
    const expanded = targets.includes('all') ? ALL_TARGETS : targets;
    const files = [];
    const archSection = buildArchitectureSection(context);
    const testSection = buildTestingSection(context);
    const secSection = buildSecuritySection();
    const allSections = [archSection, testSection, secSection];
    for (const target of expanded) {
        if (target === 'kiro') {
            // 3 separate files, one per section
            for (const section of allSections) {
                files.push({
                    target,
                    outputPath: section.filePath ?? `.kiro/steering/${section.title.toLowerCase()}.md`,
                    content: generateSteeringContent([section], target),
                    sections: [section],
                });
            }
        }
        else if (target === 'cursor') {
            files.push({
                target,
                outputPath: '.cursorrules',
                content: generateSteeringContent(allSections, target),
                sections: allSections,
            });
        }
        else if (target === 'claude') {
            files.push({
                target,
                outputPath: 'CLAUDE.md',
                content: generateSteeringContent(allSections, target),
                sections: allSections,
            });
        }
        else if (target === 'cline') {
            files.push({
                target,
                outputPath: '.clinerules',
                content: generateSteeringContent(allSections, target),
                sections: allSections,
            });
        }
        else if (target === 'copilot') {
            files.push({
                target,
                outputPath: '.github/copilot-instructions.md',
                content: generateSteeringContent(allSections, target),
                sections: allSections,
            });
        }
        else if (target === 'codex') {
            const codexSections = [...allSections];
            if (context.toolsMarkdown !== undefined && context.toolsMarkdown.length > 0) {
                codexSections.push({
                    title: 'Planu MCP Tools',
                    content: context.toolsMarkdown,
                });
            }
            files.push({
                target,
                outputPath: 'AGENTS.md',
                content: generateSteeringContent(codexSections, target),
                sections: codexSections,
            });
        }
    }
    return files;
}
/** Write steering files to disk, handling CLAUDE.md merging. */
export async function writeSteeringFiles(files, projectPath) {
    const writtenPaths = [];
    for (const file of files) {
        const absolutePath = join(projectPath, file.outputPath);
        await mkdir(dirname(absolutePath), { recursive: true });
        let finalContent = file.content;
        if (file.target === 'claude') {
            finalContent = await mergeClaudeContent(absolutePath, file.content);
        }
        await writeFile(absolutePath, finalContent, 'utf-8');
        writtenPaths.push(absolutePath);
    }
    return writtenPaths;
}
/** Merge Planu steering block into existing CLAUDE.md, or append if not found. */
async function mergeClaudeContent(filePath, steeringContent) {
    let existing = '';
    try {
        existing = await readFile(filePath, 'utf-8');
    }
    catch {
        // File does not exist yet, use empty string
    }
    const startMarker = '<!-- PLANU:STEERING:START -->';
    const endMarker = '<!-- PLANU:STEERING:END -->';
    if (existing.includes(startMarker) && existing.includes(endMarker)) {
        const startIdx = existing.indexOf(startMarker);
        const endIdx = existing.indexOf(endMarker) + endMarker.length;
        return existing.slice(0, startIdx) + steeringContent + existing.slice(endIdx);
    }
    if (existing.length === 0) {
        return steeringContent;
    }
    return `${existing}\n\n${steeringContent}`;
}
/** Format a human-readable generation report. */
export function formatGenerationReport(result) {
    const rows = result.files
        .map((f) => `| ${f.outputPath} | ${f.sections.map((s) => s.title).join(', ')} |`)
        .join('\n');
    return `## Steering Files Generated

**Target**: ${result.target}
**Files**: ${result.filesGenerated}

| File | Sections |
|------|---------|
${rows}

These files provide persistent project context to your AI tool.
Update them when project conventions change: \`generate_steering_file\``;
}
//# sourceMappingURL=steering-generator.js.map