fold/scripts/benchmarks/fold_eval/stability.py
trvon 2dcbdbc75d
feat: harden Fold quality guard
Preserve source, binary, and runtime evidence boundaries while making precision and performance regressions reproducible.

- decompose analysis orchestration into bounded modules
- add differential, metamorphic, organic, and Yams change-time gates
- fix detector, P-Code, fuzz sanitizer, and report identity precision
2026-07-13 15:05:35 -04:00

46 lines
1.3 KiB
Python

"""Repeated-run finding stability metrics."""
from __future__ import annotations
from collections.abc import Iterable, Sequence
from typing import Any
from .metrics import distribution_summary
def jaccard(left: set[str], right: set[str]) -> float:
union = left | right
return len(left & right) / len(union) if union else 1.0
def stability_summary(runs: Sequence[Iterable[str]]) -> dict[str, Any]:
sets = [set(run) for run in runs]
if not sets:
return {
"run_count": 0,
"exact": False,
"intersection_count": 0,
"union_count": 0,
"churn_count": 0,
"per_run_counts": [],
"pairwise_jaccard": distribution_summary([]),
}
intersection = set.intersection(*sets)
union = set.union(*sets)
pairwise = [
jaccard(sets[left], sets[right])
for left in range(len(sets))
for right in range(left + 1, len(sets))
]
if len(sets) == 1:
pairwise = [1.0]
return {
"run_count": len(sets),
"exact": all(current == sets[0] for current in sets[1:]),
"intersection_count": len(intersection),
"union_count": len(union),
"churn_count": len(union - intersection),
"per_run_counts": [len(current) for current in sets],
"pairwise_jaccard": distribution_summary(pairwise),
}