Skip to content

Commit dea54d0

Browse files
authored
Add utility functions for IX obligations handling
1 parent 6d84987 commit dea54d0

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

src/ix_cognition_kernel/wave6_ix_handoff.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,87 @@ def _require_unique_text(values: Iterable[str], *, label: str) -> None:
987987
seen.add(value)
988988

989989

990+
def _stable_sha256(payload: Mapping[str, Any]) -> str:
991+
"""Return deterministic SHA-256 over a canonical JSON payload."""
992+
993+
encoded = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
994+
return hashlib.sha256(encoded).hexdigest()
995+
def _probe_id(contract_artifact_id: str, obligation: WaveSixIxObligation) -> str:
996+
"""Return deterministic falsification-probe id for an IX obligation."""
997+
998+
return f"ix-obligation-probe:{contract_artifact_id}:{obligation.obligation_id}"
999+
1000+
1001+
def _sort_pressures_by_canonical_order(
1002+
pressures: Iterable[WaveSixIxObligationPressure],
1003+
) -> tuple[WaveSixIxObligationPressure, ...]:
1004+
"""Return pressure records sorted by canonical IX obligation order."""
1005+
1006+
by_id: dict[str, WaveSixIxObligationPressure] = {}
1007+
for pressure in pressures:
1008+
if pressure.obligation_id in by_id:
1009+
raise ValueError(
1010+
f"Duplicate IX obligation pressure: {pressure.obligation_id}"
1011+
)
1012+
by_id[pressure.obligation_id] = pressure
1013+
return tuple(
1014+
by_id[obligation_id]
1015+
for obligation_id in canonical_ix_cognition_obligation_ids()
1016+
if obligation_id in by_id
1017+
)
1018+
1019+
1020+
def _require_exact_obligation_ids(obligation_ids: tuple[str, ...]) -> None:
1021+
"""Require pressure coverage for every canonical IX cognition obligation."""
1022+
1023+
expected = set(canonical_ix_cognition_obligation_ids())
1024+
actual = set(obligation_ids)
1025+
missing = tuple(
1026+
obligation_id
1027+
for obligation_id in canonical_ix_cognition_obligation_ids()
1028+
if obligation_id not in actual
1029+
)
1030+
extra = tuple(sorted(actual - expected))
1031+
if missing:
1032+
raise ValueError(f"Missing IX obligation pressure: {missing[0]}")
1033+
if extra:
1034+
raise ValueError(f"Unknown IX obligation pressure: {extra[0]}")
1035+
1036+
1037+
def _unique_preserving_order(values: Iterable[str]) -> tuple[str, ...]:
1038+
"""Return unique text values while preserving first-seen order."""
1039+
1040+
seen: set[str] = set()
1041+
unique: list[str] = []
1042+
for value in values:
1043+
if value not in seen:
1044+
unique.append(value)
1045+
seen.add(value)
1046+
return tuple(unique)
1047+
1048+
1049+
def _require_non_empty(value: str, label: str) -> str:
1050+
"""Return stripped text or raise when empty."""
1051+
1052+
normalized = value.strip()
1053+
if not normalized:
1054+
raise ValueError(f"{label} must not be empty.")
1055+
return normalized
1056+
1057+
1058+
def _require_sha256(value: str, label: str) -> str:
1059+
"""Require a deterministic SHA-256 fingerprint value."""
1060+
1061+
normalized = _require_non_empty(value, label)
1062+
if len(normalized) != 64:
1063+
raise ValueError(f"{label} must be a SHA-256 fingerprint.")
1064+
try:
1065+
int(normalized, 16)
1066+
except ValueError as exc:
1067+
raise ValueError(f"{label} must be hexadecimal.") from exc
1068+
return normalized
1069+
1070+
9901071
def _stable_sha256(payload: Mapping[str, Any]) -> str:
9911072
"""Return deterministic SHA-256 over a canonical JSON payload."""
9921073

0 commit comments

Comments
 (0)