// engine/heal/recipes/json-syntax.ts — SPEC-745
// Detects and repairs broken JSON syntax using tolerant parsing.
// Falls back to stripping trailing commas and truncated content.
import { readFileSync } from 'node:fs';
/**
 * Check if a JSON file has syntax errors and attempt repair.
 * Strategy:
 *   1. Try JSON.parse — if OK, no heal needed.
 *   2. Try removing trailing commas and whitespace issues.
 *   3. Try truncation recovery (unterminated objects/arrays).
 */
export function detectAndRepairJsonSyntax(filePath) {
    let content;
    try {
        content = readFileSync(filePath, 'utf-8');
    }
    catch {
        return { needsHeal: false };
    }
    // Step 1: try direct parse
    try {
        JSON.parse(content);
        return { needsHeal: false };
    }
    catch {
        // Fall through to repair
    }
    // Step 2: remove trailing commas before } or ]
    const noTrailingCommas = content.replace(/,(\s*[}\]])/g, '$1');
    try {
        JSON.parse(noTrailingCommas);
        return { needsHeal: true, repaired: noTrailingCommas, reason: 'trailing-comma removed' };
    }
    catch {
        // Fall through
    }
    // Step 3: try progressively shorter content (truncation recovery)
    // Find the last balanced brace/bracket position
    const trimmed = tryBalancedJson(noTrailingCommas);
    if (trimmed !== null) {
        return { needsHeal: true, repaired: trimmed, reason: 'truncated-json recovered' };
    }
    // Could not repair — return a canonical default (empty object)
    return { needsHeal: true, repaired: '{}', reason: 'could not repair — reset to empty object' };
}
function tryBalancedJson(content) {
    // Walk backwards from end to find a point where JSON is valid
    for (let len = content.length - 1; len > 0; len--) {
        const candidate = content.slice(0, len);
        // Only try at brace/bracket positions
        const lastChar = candidate[candidate.length - 1];
        if (lastChar === '}' || lastChar === ']' || lastChar === '"') {
            try {
                JSON.parse(candidate);
                return candidate;
            }
            catch {
                // continue
            }
        }
    }
    return null;
}
//# sourceMappingURL=json-syntax.js.map