// engine/session-safeguard/unpushed-detector.ts — SPEC-585: Detect unpushed commits with age
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
const execFileAsync = promisify(execFile);
const MS_PER_HOUR = 3_600_000;
/** Return the current branch name or null if not in a git repo / detached HEAD. */
async function getBranch(projectPath) {
    try {
        const { stdout } = await execFileAsync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
            cwd: projectPath,
        });
        const branch = stdout.trim();
        return branch && branch !== 'HEAD' ? branch : null;
    }
    catch {
        return null;
    }
}
/**
 * List unpushed commits as Unix timestamps (author date, seconds).
 * Returns empty array when no upstream or no commits ahead.
 */
async function getUnpushedTimestamps(projectPath, branch) {
    try {
        const { stdout } = await execFileAsync('git', ['log', `origin/${branch}..HEAD`, '--format=%at'], { cwd: projectPath });
        return stdout
            .trim()
            .split('\n')
            .filter(Boolean)
            .map((line) => parseInt(line, 10))
            .filter((n) => !isNaN(n));
    }
    catch {
        return [];
    }
}
/**
 * Detect unpushed commits on the current branch.
 * Returns null when not a git repo, detached HEAD, or no upstream configured.
 */
export async function detectUnpushedCommits(projectPath) {
    const branch = await getBranch(projectPath);
    if (!branch) {
        return null;
    }
    const timestamps = await getUnpushedTimestamps(projectPath, branch);
    if (timestamps.length === 0) {
        return null;
    }
    const nowMs = Date.now();
    const oldestTimestampMs = Math.min(...timestamps) * 1000;
    const oldestAgeHours = Math.round((nowMs - oldestTimestampMs) / MS_PER_HOUR);
    return {
        count: timestamps.length,
        branch,
        oldestAgeHours,
    };
}
//# sourceMappingURL=unpushed-detector.js.map