/**
 * postcondition.mjs — subtask postcondition evaluator (C29).
 */
import { execSync } from 'node:child_process';
import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
/**
 * Evaluate a subtask postcondition predicate. Supports three shapes:
 *   { cmd: "pnpm test -- auth.spec" }        — exit code 0 = pass
 *   { file_contains: "export ...", path: "src/x.ts" }
 *   { file_exists: "src/x.ts" }
 * Returns { ok: boolean, kind, reason }. Trivially-satisfied predicates
 * (empty object, unknown shape) are REJECTED — per R3 the planner must
 * produce a real check, not a rubber stamp.
 */
export function evaluatePostcondition(pc, targetDir) {
    if (!pc || typeof pc !== 'object' || Array.isArray(pc)) {
        return { ok: false, kind: 'invalid', reason: 'postcondition is not an object' };
    }
    if (typeof pc.cmd === 'string' && pc.cmd.trim().length > 0) {
        try {
            execSync(pc.cmd, { cwd: targetDir, stdio: 'pipe', encoding: 'utf-8', timeout: 120000 });
            return { ok: true, kind: 'cmd', cmd: pc.cmd };
        }
        catch (err) {
            const stderr = err.stderr ? String(err.stderr).slice(0, 500) : '';
            const msg = err.message ? err.message.slice(0, 200) : 'non-zero exit';
            return { ok: false, kind: 'cmd', cmd: pc.cmd, reason: stderr || msg };
        }
    }
    if (typeof pc.file_contains === 'string' && typeof pc.path === 'string') {
        try {
            const content = readFileSync(join(targetDir, pc.path), 'utf-8');
            const found = content.includes(pc.file_contains);
            return {
                ok: found,
                kind: 'file_contains',
                path: pc.path,
                expected: pc.file_contains,
                reason: found ? null : 'substring not found',
            };
        }
        catch (err) {
            return {
                ok: false,
                kind: 'file_contains',
                path: pc.path,
                reason: `read failed: ${err.message}`,
            };
        }
    }
    if (typeof pc.file_exists === 'string') {
        const exists = existsSync(join(targetDir, pc.file_exists));
        return {
            ok: exists,
            kind: 'file_exists',
            path: pc.file_exists,
            reason: exists ? null : 'file missing',
        };
    }
    return {
        ok: false,
        kind: 'unknown',
        reason: 'postcondition shape not recognized (need cmd | file_contains+path | file_exists)',
    };
}
//# sourceMappingURL=postcondition.mjs.map