const SHA256_PATTERN = /^[a-f0-9]{64}$/; export type ReimportSourceMatch = 'match' | 'reference-unavailable' | 'mismatch'; /** * A reimport must contain exactly the same source files as the scan run it * replaces. Sorting preserves multiplicity, so duplicate hashes cannot hide a * missing or additional file in a multi-file scanner report. */ export function compareReimportSourceHashes( expected: readonly (string | undefined)[], candidate: readonly (string | undefined)[] ): ReimportSourceMatch { if (!expected.length || expected.some(hash => !hash || !SHA256_PATTERN.test(hash))) return 'reference-unavailable'; if (candidate.length !== expected.length || candidate.some(hash => !hash || !SHA256_PATTERN.test(hash))) return 'mismatch'; const expectedSorted = [...expected].sort(); const candidateSorted = candidate as readonly string[]; return [...candidateSorted].sort().every((hash, index) => hash === expectedSorted[index]) ? 'match' : 'mismatch'; }