// engine/errors/error-wrapper.ts — SPEC-902: Wrap errors into structured format
const WHAT_MAX = 120;
const WHY_MAX = 500;
export function isStructuredError(x) {
    if (x === null || typeof x !== 'object') {
        return false;
    }
    const obj = x;
    return obj.ok === false && typeof obj.what === 'string' && typeof obj.nextAction === 'object';
}
export function wrapError(err, ctx) {
    // Idempotency: already-wrapped errors pass through unchanged
    if (isStructuredError(err)) {
        return err;
    }
    const rule = ctx.registry.match(err);
    const rawMessage = errorMessage(err);
    if (rule) {
        return {
            ok: false,
            what: truncate(rule.what, WHAT_MAX),
            why: truncate(rule.why ?? sanitize(rawMessage), WHY_MAX),
            nextAction: rule.nextAction,
            errorCode: rule.id,
            citations: extractCitations(rawMessage),
        };
    }
    // Fallback for unknown errors
    return {
        ok: false,
        what: truncate('Tool failed', WHAT_MAX),
        why: truncate(sanitize(rawMessage), WHY_MAX),
        nextAction: {
            tool: 'workspace_alerts',
            args: {},
            rationale: 'Check for issues that may need attention.',
        },
        citations: extractCitations(rawMessage),
    };
}
function errorMessage(err) {
    if (err instanceof Error) {
        return err.message;
    }
    if (typeof err === 'string') {
        return err;
    }
    if (err === null || err === undefined) {
        return 'Unknown error';
    }
    try {
        return JSON.stringify(err);
    }
    catch {
        return 'Unknown error';
    }
}
function sanitize(raw) {
    // Strip stack traces
    let s = raw.replace(/\n\s+at\s.+/gs, '');
    // Strip error prefix
    s = s.replace(/^Error:\s*/i, '');
    s = s.replace(/^E[A-Z]+:\s*/, '');
    // Redact home paths
    s = s.replace(/\/Users\/[^/\s]+/g, '~');
    s = s.replace(/\/home\/[^/\s]+/g, '~');
    return s.trim();
}
function extractCitations(raw) {
    const matches = raw.match(/[^/\s]+\.ts:\d+/g);
    if (!matches || matches.length === 0) {
        return undefined;
    }
    return [...new Set(matches)].slice(0, 5);
}
function truncate(text, max) {
    if (text.length <= max) {
        return text;
    }
    return text.slice(0, max - 1) + '…';
}
//# sourceMappingURL=error-wrapper.js.map