serializer.py python
61 lines 1.9 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 1 day ago
1 """Deterministic YAML serializer for freeze blocks (§K5.7)."""
2
3 from __future__ import annotations
4
5 from typing import Any
6
7 import yaml
8
9
10 def _ordered_mapping_items(data: dict[str, Any]) -> list[tuple[str, Any]]:
11 """Preserve existing keys' relative order; place ``review_stamp`` per §K5.7.
12
13 Contract: preserve existing keys' relative order; place ``review_stamp`` after
14 ``frozen_inputs`` if present, else after ``outputs``, else last.
15 """
16 stamp_present = "review_stamp" in data
17 items: list[tuple[str, Any]] = [
18 (key, value) for key, value in data.items() if key != "review_stamp"
19 ]
20 if not stamp_present:
21 return items
22
23 keys = [key for key, _ in items]
24 if "frozen_inputs" in keys:
25 insert_at = keys.index("frozen_inputs") + 1
26 elif "outputs" in keys:
27 insert_at = keys.index("outputs") + 1
28 else:
29 insert_at = len(items)
30 items.insert(insert_at, ("review_stamp", data["review_stamp"]))
31 return items
32
33
34 def dump_freeze_mapping(data: dict[str, Any]) -> str:
35 """Serialize a freeze mapping deterministically (round-trip stable)."""
36 ordered = dict(_ordered_mapping_items(data))
37 text = yaml.safe_dump(
38 ordered,
39 sort_keys=False,
40 allow_unicode=True,
41 default_flow_style=False,
42 width=10_000,
43 )
44 if not text.endswith("\n"):
45 text += "\n"
46 return text
47
48
49 def parse_freeze_mapping(text: str) -> dict[str, Any]:
50 """Parse YAML mapping text for a freeze block."""
51 parsed = yaml.safe_load(text)
52 if not isinstance(parsed, dict):
53 raise ValueError("freeze block must be a mapping")
54 return parsed
55
56
57 def round_trip_stable(data: dict[str, Any]) -> bool:
58 """Return True when serialize(parse(serialize(x))) is byte-stable."""
59 once = dump_freeze_mapping(data)
60 twice = dump_freeze_mapping(parse_freeze_mapping(once))
61 return once == twice
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 1 day ago