/**
 * Source-version provenance — records WHICH version of a source was analysed,
 * written to `<run>/facts/source-version.json`. Answers "what exact tree did
 * this spec come from?" without copying the tree into the run dir.
 *
 * Git repo  → the commit/branch/dirty/remote (which, in attach/create-standard
 *             mode, equals the gitnexus index's recorded `lastCommit`).
 * Plain dir → no git block; the caller can still record a content fingerprint.
 */
import { execFileSync } from 'child_process';
/** Read git provenance for `dir`, or null when it isn't a git repo. */
export function readGitInfo(dir) {
    const run = (args) => execFileSync('git', ['-C', dir, ...args], {
        encoding: 'utf8',
        stdio: ['ignore', 'pipe', 'ignore'],
        timeout: 5000,
    }).trim();
    try {
        const commit = run(['rev-parse', 'HEAD']); // throws if not a git repo
        let branch = '';
        try {
            branch = run(['rev-parse', '--abbrev-ref', 'HEAD']);
        }
        catch { /* detached */ }
        let dirty = false;
        try {
            dirty = run(['status', '--porcelain']).length > 0;
        }
        catch { /* ignore */ }
        let remoteUrl = null;
        try {
            remoteUrl = run(['remote', 'get-url', 'origin']) || null;
        }
        catch { /* no remote */ }
        return { commit, branch, dirty, remoteUrl };
    }
    catch {
        return null;
    }
}
/** Build the source-version record for a run. */
export function buildSourceVersion(sourcePath, opts = {}) {
    return {
        schemaVersion: '2.0',
        sourcePath,
        mode: opts.mode,
        scope: opts.scope && opts.scope.length > 0 ? opts.scope : undefined,
        git: readGitInfo(sourcePath),
        scannedAt: new Date().toISOString(),
    };
}
//# sourceMappingURL=provenance.js.map