Files
Open_Ultra_SAST/src/openultrasast/complexity/ledger.py
T
Marius CiepluchandClaude Fable 5.1 f5a904b7f2 chore(p0): retire regress, the skill router, the module audit tool and vocabulary.sc
Off every active line (PATHFINDER-2026-10-13/03-unified-proposal.md, cuts).
Deleted: src/openultrasast/regress/ and the deep-mode REGRESS branch (deep
now records a regress_retired degradation and equals standard; proof is the
search-with-proof arm's job), the sandbox docker runner and probe that only
regress used, --fail-on worth-fixing, RegressConfig, the two ledger helpers
only regress called; skills.py and index.py with the hunter pool's skill
routing; model/audit.py; cpg/queries/vocabulary.sc with
benchmarks/push/ontology_gap.py. Docs and the scan skill describe the
retirement. Net: 3,895 lines deleted, 86 added. Targeted tests: 180 passed,
28 skipped; 3,331 tests collect.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-10-13 10:50:01 +02:00

129 lines
3.9 KiB
Python

"""Loop-owned complexity ledger: overlay hotspot scores without hiding sev-5 inventory."""
from __future__ import annotations
import json
from collections.abc import Mapping, Sequence
from dataclasses import asdict, dataclass, replace
from pathlib import Path
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .map import Hotspot
TRIGGERABLE_DELTA = 1.5
NOT_TRIGGERABLE_DELTA = -1.5
VERDICT_DELTAS = {
"triggerable": TRIGGERABLE_DELTA,
"not_triggerable": NOT_TRIGGERABLE_DELTA,
}
@dataclass(frozen=True)
class LedgerEntry:
score_delta: float
last_verdict: str
round: int = 0
def hotspot_key(path: str, function_name: str | None) -> str:
return f"{path}:{function_name or ''}"
def load_ledger(path: Path | None) -> dict[str, LedgerEntry]:
if path is None or not path.exists():
return {}
payload = json.loads(path.read_text())
entries: dict[str, LedgerEntry] = {}
for key, value in payload.items():
entry = _coerce_entry(value)
if entry is not None:
entries[str(key)] = entry
return entries
def write_ledger(path: Path, ledger: Mapping[str, LedgerEntry | Mapping[str, object]]) -> None:
payload: dict[str, dict[str, object]] = {}
for key, value in ledger.items():
entry = _coerce_entry(value)
if entry is None:
continue
payload[str(key)] = asdict(entry)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n")
def record_verdict(
ledger: Mapping[str, LedgerEntry | Mapping[str, object]],
*,
path: str,
function_name: str | None,
verdict: str,
) -> dict[str, LedgerEntry]:
updated: dict[str, LedgerEntry] = {}
for key, value in ledger.items():
entry = _coerce_entry(value)
if entry is not None:
updated[str(key)] = entry
key = hotspot_key(path, function_name)
previous = updated.get(key)
updated[key] = LedgerEntry(
score_delta=round((previous.score_delta if previous else 0.0) + VERDICT_DELTAS.get(verdict, 0.0), 4),
last_verdict=verdict,
round=(previous.round if previous else 0) + 1,
)
return updated
def apply_overlay(
hotspots: Sequence[Hotspot],
ledger: Mapping[str, LedgerEntry | Mapping[str, object]],
) -> tuple[Hotspot, ...]:
if not ledger:
return tuple(hotspots)
adjusted: list[Hotspot] = []
for hotspot in hotspots:
entry = _coerce_entry(ledger.get(hotspot_key(hotspot.path, hotspot.function_name)))
if entry is None or entry.score_delta == 0.0:
adjusted.append(hotspot)
continue
score = round(hotspot.score + entry.score_delta, 4)
signals = dict(hotspot.signals)
signals["ledger_delta"] = entry.score_delta
adjusted.append(
replace(
hotspot,
score=score,
band=_band_for(score),
signals=signals,
rationale=(
f"{hotspot.rationale} ledger overlay last_verdict={entry.last_verdict} "
f"score_delta={entry.score_delta} (inventory retained)."
),
)
)
return tuple(sorted(adjusted, key=lambda item: (-item.score, item.path, item.function_name or "")))
def _coerce_entry(value: object) -> LedgerEntry | None:
if isinstance(value, LedgerEntry):
return value
if not isinstance(value, Mapping):
return None
raw_delta = value.get("score_delta")
if isinstance(raw_delta, bool) or not isinstance(raw_delta, int | float):
return None
raw_round = value.get("round", 0)
round_n = raw_round if isinstance(raw_round, int) and not isinstance(raw_round, bool) else 0
return LedgerEntry(
score_delta=float(raw_delta),
last_verdict=str(value.get("last_verdict", "")),
round=round_n,
)
def _band_for(score: float) -> str:
from .map import _band
return _band(score)