/**
 * Nexus Prime — Bootstrap Registry
 *
 * Durable, file-backed storage for BootstrapReceipt.
 * Survives process restarts — the MCP adapter checks this instead of
 * depending solely on the ephemeral SessionTelemetry.bootstrapped flag.
 *
 * Stored as JSON in the workspace state directory:
 *   <stateRoot>/bootstrap-receipt.json
 */
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
import { join } from 'path';
import { execSync } from 'child_process';
const RECEIPT_FILENAME = 'bootstrap-receipt.json';
/** Maximum age (ms) before a receipt is considered stale. Default: 6 hours. */
const MAX_RECEIPT_AGE_MS = 6 * 60 * 60 * 1000;
/**
 * Write a bootstrap receipt to the workspace state directory.
 */
export function writeBootstrapReceipt(stateRoot, receipt) {
    if (!existsSync(stateRoot)) {
        mkdirSync(stateRoot, { recursive: true });
    }
    const filePath = join(stateRoot, RECEIPT_FILENAME);
    writeFileSync(filePath, JSON.stringify(receipt, null, 2), 'utf8');
}
/**
 * Read the bootstrap receipt, if it exists and is not stale.
 * Returns null if missing, corrupt, or older than MAX_RECEIPT_AGE_MS.
 */
export function readBootstrapReceipt(stateRoot) {
    const filePath = join(stateRoot, RECEIPT_FILENAME);
    if (!existsSync(filePath))
        return null;
    try {
        const raw = readFileSync(filePath, 'utf8');
        const receipt = JSON.parse(raw);
        // Staleness check: discard receipts older than threshold
        if (Date.now() - receipt.bootstrappedAt > MAX_RECEIPT_AGE_MS) {
            return null;
        }
        return receipt;
    }
    catch {
        return null;
    }
}
/**
 * Check whether a valid (non-stale) bootstrap receipt exists.
 */
export function hasValidBootstrapReceipt(stateRoot) {
    return readBootstrapReceipt(stateRoot) !== null;
}
/**
 * Remove the bootstrap receipt (e.g. on explicit session reset).
 */
export function clearBootstrapReceipt(stateRoot) {
    const filePath = join(stateRoot, RECEIPT_FILENAME);
    try {
        if (existsSync(filePath))
            unlinkSync(filePath);
    }
    catch {
        // Best-effort cleanup
    }
}
/**
 * Build a RepoIdentity from the current working directory.
 */
export function buildRepoIdentity(repoRoot) {
    const repoName = repoRoot.split('/').pop() ?? 'unknown';
    let gitHead;
    try {
        gitHead = execSync('git rev-parse HEAD', {
            cwd: repoRoot,
            encoding: 'utf8',
            timeout: 2000,
        }).trim();
    }
    catch {
        // Not a git repo or git not available
    }
    return { repoRoot, repoName, gitHead };
}
/**
 * Check whether a receipt's repo identity is still current
 * (i.e. the repo root matches and HEAD hasn't changed drastically).
 */
export function isReceiptCurrent(receipt, currentRepoRoot) {
    if (receipt.repoIdentity.repoRoot !== currentRepoRoot)
        return false;
    // HEAD change is allowed (commits happen) — only check root mismatch
    return true;
}
