import { nowIso, randomId } from '../fsx.js';
export const EVIDENCE_SCHEMA = 'sks.evidence.v1';
export const EVIDENCE_INDEX_SCHEMA = 'sks.evidence-index.v1';
export const PROJECT_EVIDENCE_INDEX_SCHEMA = 'sks.project-evidence-index.v1';
export const EVIDENCE_KINDS = Object.freeze([
    'agent',
    'image_voxel',
    'db_safety',
    'hook',
    'codex_lb',
    'test',
    'file_change',
    'command',
    'rust',
    'blackbox',
    'proof',
    'route_contract',
    'trust_report',
    'route_gate',
    'ux_review_source_screenshot',
    'ux_review_gpt_image_2_callout',
    'ux_review_callout_extraction',
    'ux_review_patch_result',
    'ux_review_recheck',
    'wrongness',
    'image_wrongness',
    'correction',
    'avoidance_rule',
    'artifact'
]);
export const EVIDENCE_SOURCES = Object.freeze([
    'real',
    'mock',
    'static_contract',
    'fixture',
    'blocked'
]);
export const EVIDENCE_FRESHNESS = Object.freeze([
    'fresh',
    'stale',
    'unknown'
]);
export const EVIDENCE_TRUST = Object.freeze([
    'high',
    'medium',
    'low',
    'blocked'
]);
function asRecord(value) {
    return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
}
function stringOrNull(value) {
    return typeof value === 'string' ? value : null;
}
function stringList(value) {
    return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : [];
}
function isOneOf(values, value) {
    return typeof value === 'string' && values.includes(value);
}
export function evidenceId(kind = 'artifact') {
    return `EV-${String(kind || 'artifact').replace(/[^A-Za-z0-9]+/g, '-').replace(/^-|-$/g, '').toUpperCase() || 'ART'}-${randomId(8)}`;
}
export function normalizeEvidenceKind(kind = 'artifact') {
    return isOneOf(EVIDENCE_KINDS, kind) ? kind : 'artifact';
}
export function normalizeEvidenceSource(source = 'real') {
    return isOneOf(EVIDENCE_SOURCES, source) ? source : 'real';
}
export function normalizeEvidenceFreshness(freshness = 'unknown') {
    return isOneOf(EVIDENCE_FRESHNESS, freshness) ? freshness : 'unknown';
}
export function normalizeEvidenceTrust(trust = 'low') {
    return isOneOf(EVIDENCE_TRUST, trust) ? trust : 'low';
}
export function createEvidenceRecord(input = {}) {
    const record = asRecord(input);
    const source = normalizeEvidenceSource(record.source);
    const freshness = normalizeEvidenceFreshness(record.freshness);
    return {
        schema: EVIDENCE_SCHEMA,
        id: stringOrNull(record.id) || evidenceId(record.kind),
        mission_id: stringOrNull(record.mission_id),
        kind: normalizeEvidenceKind(record.kind),
        source,
        path: stringOrNull(record.path),
        sha256: stringOrNull(record.sha256),
        created_at: stringOrNull(record.created_at) || nowIso(),
        freshness,
        trust: normalizeEvidenceTrust(record.trust || trustForEvidence({ source, freshness, blocked: record.blocked })),
        redacted: record.redacted !== false,
        issues: stringList(record.issues)
    };
}
export function trustForEvidence(input = {}) {
    const record = asRecord(input);
    const source = normalizeEvidenceSource(record.source);
    const freshness = normalizeEvidenceFreshness(record.freshness);
    const blocked = Boolean(record.blocked);
    if (blocked || source === 'blocked')
        return 'blocked';
    if (freshness === 'stale')
        return 'blocked';
    if (source === 'mock' || source === 'static_contract')
        return 'low';
    if (source === 'fixture')
        return 'medium';
    return freshness === 'fresh' ? 'high' : 'medium';
}
export function validateEvidenceRecord(record = {}) {
    const issues = [];
    const row = asRecord(record);
    if (row.schema !== EVIDENCE_SCHEMA)
        issues.push('schema');
    if (!row.id)
        issues.push('id');
    if (!isOneOf(EVIDENCE_KINDS, row.kind))
        issues.push('kind');
    if (!isOneOf(EVIDENCE_SOURCES, row.source))
        issues.push('source');
    if (!isOneOf(EVIDENCE_FRESHNESS, row.freshness))
        issues.push('freshness');
    if (!isOneOf(EVIDENCE_TRUST, row.trust))
        issues.push('trust');
    if (row.path && !row.sha256)
        issues.push('sha256');
    if ((row.source === 'mock' || row.source === 'static_contract') && row.trust === 'high')
        issues.push('mock_high_trust');
    if (row.freshness === 'stale' && row.trust !== 'blocked')
        issues.push('stale_not_blocked');
    return { ok: issues.length === 0, issues };
}
export function isEvidenceRecord(value) {
    if (!value || typeof value !== 'object')
        return false;
    const row = value;
    return row.schema === EVIDENCE_SCHEMA
        && typeof row.id === 'string'
        && typeof row.kind === 'string'
        && typeof row.source === 'string'
        && (row.path === null || typeof row.path === 'string')
        && (row.sha256 === null || typeof row.sha256 === 'string')
        && Array.isArray(row.issues);
}
//# sourceMappingURL=evidence-schema.js.map