/**
 * src/skill-loop/sign-off.ts
 *
 * Article 14 human oversight mechanism for skill promotion.
 *
 * Invariants:
 *   - Audit trail: { approver_id, timestamp, decision, rationale, signed_hash }
 *   - signed_hash = SHA-256(candidateId + decision + rationale + isoTimestamp)
 *   - Escalation: approver unavailable >72h → auto-REJECTED (never auto-approved)
 *   - Multiple approvers possible; one sign-off is sufficient for promotion.
 *
 * @module skill-loop/sign-off
 */
export type SignOffDecision = "approved" | "rejected";
export interface SignOffRecord {
    /** Candidate ID this sign-off covers. */
    candidateId: string;
    /** Identifier of the human approver (e.g. user UUID or username). */
    approverId: string;
    /** ISO-8601 timestamp at which the decision was recorded. */
    timestamp: string;
    /** Human decision. */
    decision: SignOffDecision;
    /** Human-provided rationale (non-empty required). */
    rationale: string;
    /**
     * Integrity hash: SHA-256(candidateId + decision + rationale + timestamp).
     * Detects tampering in the audit trail.
     */
    signedHash: string;
}
export interface PendingRequest {
    candidateId: string;
    requestedAt: string;
    /** Approver ID if a specific approver is designated. Null = any approver. */
    approverId: string | null;
    /** Deadline beyond which the request is auto-rejected (72h from requestedAt). */
    deadlineAt: string;
}
/**
 * Manages pending approval requests and sign-off records.
 *
 * In production, records should be persisted to the DB. This implementation
 * is in-memory and suitable for tests and single-process environments.
 */
export declare class SignOffManager {
    private readonly records;
    private readonly pending;
    /** 72-hour escalation deadline in milliseconds. */
    static readonly ESCALATION_DEADLINE_MS: number;
    /**
     * Create a pending approval request for a candidate.
     *
     * If a request already exists and is not expired, returns the existing one.
     */
    requestSignOff(candidateId: string, approverId?: string | null, nowDate?: Date): PendingRequest;
    /**
     * Record a sign-off decision (approved or rejected).
     *
     * @throws If rationale is empty or candidateId is missing.
     */
    recordDecision(candidateId: string, approverId: string, decision: SignOffDecision, rationale: string, nowDate?: Date): SignOffRecord;
    /**
     * Check all pending requests and auto-reject any that have exceeded the 72h deadline.
     *
     * @returns Array of auto-rejection records created.
     */
    escalateExpired(nowDate?: Date): SignOffRecord[];
    /**
     * Returns the first approved sign-off for a candidate, or null if none exists.
     * One sign-off is sufficient for promotion.
     */
    getApproval(candidateId: string): SignOffRecord | null;
    /**
     * Returns all sign-off records for a candidate (audit trail).
     */
    getAuditTrail(candidateId: string): SignOffRecord[];
    /**
     * Returns true if a pending request exists and has not expired.
     */
    hasPending(candidateId: string, nowDate?: Date): boolean;
    /**
     * Verify the integrity of a sign-off record by recomputing its hash.
     */
    verifyRecord(record: SignOffRecord): boolean;
    private isExpired;
}
//# sourceMappingURL=sign-off.d.ts.map