Skip to content

Commit f0c10fd

Browse files
authored
refactor(operator-trend): collapse rererestore tier shims + golden net (T3-2 phase 1) (#74)
* test(operator-trend): characterize restore-tier fractal with golden contract Pin the exact current output of every pure (status:str)->str classifier in the restore-tier depth machinery (30 functions x 265 status inputs) to a golden file, generated by executing the modules. Safety net for the upcoming recovery_state depth-collapse: any change to depth-tier translation surfaces as a byte diff before it can reach a consumer. * refactor(operator-trend): collapse rererestore tier shims onto a primitive The four restore-tier translation shims hand-spelled every depth-shifted output string (restore <-> rerestore <-> rererestore <-> rerererestore), cloning the tier arithmetic four ways. Replace the spelled-out value maps with a single _shift_restore_tier(token, delta) primitive plus recognized-input sets; the shims become thin delegators. Proven byte-identical by the restore-tier golden contract (30 classifiers x 265 inputs). First scalar-primitive slice of the operator_resolution_trend fractal collapse.
1 parent a947957 commit f0c10fd

4 files changed

Lines changed: 8305 additions & 69 deletions

src/operator_trend_closure_forecast_reset_controls.py

Lines changed: 94 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8188,85 +8188,110 @@ def _rerererestore_text(text: str) -> str:
81888188
return transformed
81898189

81908190

8191+
# Restore-tier depth arithmetic. A restore-tier word is "store"/"stored"/"storing"
8192+
# prefixed by one "re" per depth level: restore(1) -> rerestore(2) -> rererestore(3)
8193+
# -> rerererestore(4). The translation shims below previously hand-spelled every
8194+
# depth-shifted output string; they now share this single primitive, which moves a
8195+
# status token's restore tier by `delta` levels (passthrough/unknown tokens carry no
8196+
# tier word and are returned unchanged).
8197+
_RESTORE_TIER_BASES = ("storing", "stored", "store")
8198+
8199+
8200+
def _shift_restore_tier(token: str, delta: int) -> str:
8201+
parts = token.split("-")
8202+
for index, part in enumerate(parts):
8203+
for base in _RESTORE_TIER_BASES:
8204+
if not part.endswith(base):
8205+
continue
8206+
prefix = part[: -len(base)]
8207+
if not prefix or len(prefix) % 2 or prefix != "re" * (len(prefix) // 2):
8208+
return token
8209+
new_depth = len(prefix) // 2 + delta
8210+
if new_depth < 1:
8211+
return token
8212+
parts[index] = "re" * new_depth + base
8213+
return "-".join(parts)
8214+
return token
8215+
8216+
8217+
def _translate_restore_tier_status(status: str, *, delta: int, recognized: frozenset[str]) -> str:
8218+
# Recognized inputs are translated by shifting their restore tier `delta` levels.
8219+
# Passthrough terms (none/blocked/reversing/insufficient-data) are recognized but
8220+
# carry no tier word, so the shift returns them unchanged. Anything else -> "none".
8221+
if status in recognized:
8222+
return _shift_restore_tier(status, delta)
8223+
return "none"
8224+
8225+
8226+
_STATUS_TO_RERERESTORE_INPUTS = frozenset(
8227+
{
8228+
"pending-confirmation-rebuild-reentry-rerererestore",
8229+
"pending-clearance-rebuild-reentry-rerererestore",
8230+
"rerererestored-confirmation-rebuild-reentry",
8231+
"rerererestored-clearance-rebuild-reentry",
8232+
"blocked",
8233+
"none",
8234+
}
8235+
)
8236+
_PERSISTENCE_TO_RERERESTORE_INPUTS = frozenset(
8237+
{
8238+
"just-rerererestored",
8239+
"holding-confirmation-rebuild-reentry-rerererestore",
8240+
"holding-clearance-rebuild-reentry-rerererestore",
8241+
"sustained-confirmation-rebuild-reentry-rerererestore",
8242+
"sustained-clearance-rebuild-reentry-rerererestore",
8243+
"reversing",
8244+
"insufficient-data",
8245+
"none",
8246+
}
8247+
)
8248+
_REFRESH_TO_RERERESTORE_INPUTS = frozenset(
8249+
{
8250+
"recovering-confirmation-rebuild-reentry-rererestore-reset",
8251+
"recovering-clearance-rebuild-reentry-rererestore-reset",
8252+
"rerererestoring-confirmation-rebuild-reentry",
8253+
"rerererestoring-clearance-rebuild-reentry",
8254+
"reversing",
8255+
"blocked",
8256+
"none",
8257+
}
8258+
)
8259+
_PERSISTENCE_FROM_RERERESTORE_INPUTS = frozenset(
8260+
{
8261+
"just-rererestored",
8262+
"holding-confirmation-rebuild-reentry-rererestore",
8263+
"holding-clearance-rebuild-reentry-rererestore",
8264+
"sustained-confirmation-rebuild-reentry-rererestore",
8265+
"sustained-clearance-rebuild-reentry-rererestore",
8266+
"reversing",
8267+
"insufficient-data",
8268+
"none",
8269+
}
8270+
)
8271+
8272+
81918273
def _status_to_rererestore_status(status: str) -> str:
8192-
return {
8193-
"pending-confirmation-rebuild-reentry-rerererestore": (
8194-
"pending-confirmation-rebuild-reentry-rererestore"
8195-
),
8196-
"pending-clearance-rebuild-reentry-rerererestore": (
8197-
"pending-clearance-rebuild-reentry-rererestore"
8198-
),
8199-
"rerererestored-confirmation-rebuild-reentry": (
8200-
"rererestored-confirmation-rebuild-reentry"
8201-
),
8202-
"rerererestored-clearance-rebuild-reentry": (
8203-
"rererestored-clearance-rebuild-reentry"
8204-
),
8205-
"blocked": "blocked",
8206-
"none": "none",
8207-
}.get(status, "none")
8274+
return _translate_restore_tier_status(
8275+
status, delta=-1, recognized=_STATUS_TO_RERERESTORE_INPUTS
8276+
)
82088277

82098278

82108279
def _persistence_status_to_rererestore_status(status: str) -> str:
8211-
return {
8212-
"just-rerererestored": "just-rererestored",
8213-
"holding-confirmation-rebuild-reentry-rerererestore": (
8214-
"holding-confirmation-rebuild-reentry-rererestore"
8215-
),
8216-
"holding-clearance-rebuild-reentry-rerererestore": (
8217-
"holding-clearance-rebuild-reentry-rererestore"
8218-
),
8219-
"sustained-confirmation-rebuild-reentry-rerererestore": (
8220-
"sustained-confirmation-rebuild-reentry-rererestore"
8221-
),
8222-
"sustained-clearance-rebuild-reentry-rerererestore": (
8223-
"sustained-clearance-rebuild-reentry-rererestore"
8224-
),
8225-
"reversing": "reversing",
8226-
"insufficient-data": "insufficient-data",
8227-
"none": "none",
8228-
}.get(status, "none")
8280+
return _translate_restore_tier_status(
8281+
status, delta=-1, recognized=_PERSISTENCE_TO_RERERESTORE_INPUTS
8282+
)
82298283

82308284

82318285
def _refresh_status_to_rererestore_refresh_status(status: str) -> str:
8232-
return {
8233-
"recovering-confirmation-rebuild-reentry-rererestore-reset": (
8234-
"recovering-confirmation-rebuild-reentry-rerestore-reset"
8235-
),
8236-
"recovering-clearance-rebuild-reentry-rererestore-reset": (
8237-
"recovering-clearance-rebuild-reentry-rerestore-reset"
8238-
),
8239-
"rerererestoring-confirmation-rebuild-reentry": (
8240-
"rererestoring-confirmation-rebuild-reentry"
8241-
),
8242-
"rerererestoring-clearance-rebuild-reentry": (
8243-
"rererestoring-clearance-rebuild-reentry"
8244-
),
8245-
"reversing": "reversing",
8246-
"blocked": "blocked",
8247-
"none": "none",
8248-
}.get(status, "none")
8286+
return _translate_restore_tier_status(
8287+
status, delta=-1, recognized=_REFRESH_TO_RERERESTORE_INPUTS
8288+
)
82498289

82508290

82518291
def _persistence_status_from_rererestore_status(status: str) -> str:
8252-
return {
8253-
"just-rererestored": "just-rerererestored",
8254-
"holding-confirmation-rebuild-reentry-rererestore": (
8255-
"holding-confirmation-rebuild-reentry-rerererestore"
8256-
),
8257-
"holding-clearance-rebuild-reentry-rererestore": (
8258-
"holding-clearance-rebuild-reentry-rerererestore"
8259-
),
8260-
"sustained-confirmation-rebuild-reentry-rererestore": (
8261-
"sustained-confirmation-rebuild-reentry-rerererestore"
8262-
),
8263-
"sustained-clearance-rebuild-reentry-rererestore": (
8264-
"sustained-clearance-rebuild-reentry-rerererestore"
8265-
),
8266-
"reversing": "reversing",
8267-
"insufficient-data": "insufficient-data",
8268-
"none": "none",
8269-
}.get(status, "none")
8292+
return _translate_restore_tier_status(
8293+
status, delta=1, recognized=_PERSISTENCE_FROM_RERERESTORE_INPUTS
8294+
)
82708295

82718296

82728297
def _translate_target_for_persistence(target: dict[str, Any]) -> dict[str, Any]:
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
"""Golden-contract enumerator for the operator_resolution_trend restore-tier fractal.
2+
3+
Captures the EXACT current output of every pure ``(status: str) -> str`` classifier
4+
across the full restore-tier status-string vocabulary (depths 1-4), into a golden
5+
JSON file. After the ``recovery_state(target, *, depth)`` collapse, re-run this and
6+
diff the JSON: byte-identical output proves the collapse preserved the contract.
7+
8+
Safety: only imports pure-computation modules (verified free of import-time DB/IO
9+
side effects) and calls pure string classifiers. Never opens a live database.
10+
11+
Run from the repo root: ``uv run python tests/golden/enumerate_recovery_state_contract.py``
12+
"""
13+
14+
from __future__ import annotations
15+
16+
import ast
17+
import inspect
18+
import json
19+
import re
20+
from pathlib import Path
21+
from types import ModuleType
22+
23+
import src.operator_resolution_trend as m_resolution
24+
import src.operator_snapshot_packaging as m_pkg
25+
import src.operator_trend_closure_forecast_reacquisition_controls as m_reacq
26+
import src.operator_trend_closure_forecast_reset_controls as m_reset
27+
28+
REPO = Path(__file__).resolve().parents[2]
29+
GOLDEN_PATH = REPO / "tests" / "golden" / "recovery_state_contract.golden.json"
30+
31+
# The restore-tier axis: depth == number of "re" prefixes on "store".
32+
PREFIXES = ("holding", "pending", "sustained", "recovering")
33+
SIDES = ("clearance", "confirmation")
34+
TIERS = ("restore", "rerestore", "rererestore", "rerererestore")
35+
TIERS_DONE = ("restored", "rerestored", "rererestored", "rerererestored")
36+
37+
38+
def _family_persistence() -> list[str]:
39+
out: list[str] = []
40+
for prefix in PREFIXES:
41+
for side in SIDES:
42+
for tier in TIERS:
43+
base = f"{prefix}-{side}-rebuild-reentry-{tier}"
44+
out.append(f"{base}-reset" if prefix == "recovering" else base)
45+
return out
46+
47+
48+
def _family_done() -> list[str]:
49+
return [f"{tier}-{side}-rebuild-reentry" for tier in TIERS_DONE for side in SIDES]
50+
51+
52+
def _family_just() -> list[str]:
53+
return [f"just-{tier}" for tier in TIERS_DONE]
54+
55+
56+
# Boundary inputs every classifier must still tolerate.
57+
BOUNDARY = (
58+
"none",
59+
"",
60+
"hold",
61+
"reentered-clearance-rebuild",
62+
"reentered-confirmation-rebuild",
63+
"restoring-confirmation-rebuild-reentry",
64+
"restoring-clearance-rebuild-reentry",
65+
)
66+
67+
# Status-token shape: a lowercase, hyphen-joined single token (no spaces). This is
68+
# exactly the form of every dict key / branch literal the classifiers discriminate
69+
# on (e.g. "holding-clearance-rebuild-reentry-rererestore", "insufficient-data",
70+
# "just-restored", "none"). Harvesting these from source guarantees every branch of
71+
# every dict-lookup table is exercised — a golden of all-"none" would be worthless.
72+
_STATUS_TOKEN = re.compile(r"^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$")
73+
74+
75+
def _harvest_status_literals(modules: tuple[ModuleType, ...]) -> set[str]:
76+
harvested: set[str] = set()
77+
for module in modules:
78+
source = Path(inspect.getfile(module)).read_text()
79+
for node in ast.walk(ast.parse(source)):
80+
if isinstance(node, ast.Constant) and isinstance(node.value, str):
81+
value = node.value
82+
if _STATUS_TOKEN.match(value) and len(value) <= 80:
83+
harvested.add(value)
84+
return harvested
85+
86+
87+
_MODULES: tuple[ModuleType, ...] = (m_resolution, m_reset, m_reacq, m_pkg)
88+
89+
VOCAB: tuple[str, ...] = tuple(
90+
sorted(
91+
set(_family_persistence())
92+
| set(_family_done())
93+
| set(_family_just())
94+
| set(BOUNDARY)
95+
| _harvest_status_literals(_MODULES)
96+
)
97+
)
98+
99+
100+
def _is_str_annotation(annotation: object) -> bool:
101+
# ``from __future__ import annotations`` makes annotations strings, not types.
102+
return annotation is str or annotation == "str"
103+
104+
105+
def _pure_status_classifiers(module: ModuleType) -> dict[str, object]:
106+
"""Single-parameter ``str -> str`` functions defined in *module* (not imported)."""
107+
found: dict[str, object] = {}
108+
for name, fn in inspect.getmembers(module, inspect.isfunction):
109+
if fn.__module__ != module.__name__:
110+
continue
111+
sig = inspect.signature(fn)
112+
params = list(sig.parameters.values())
113+
if len(params) != 1:
114+
continue
115+
(only,) = params
116+
if _is_str_annotation(only.annotation) and _is_str_annotation(sig.return_annotation):
117+
found[name] = fn
118+
return found
119+
120+
121+
def main() -> None:
122+
golden: dict[str, dict[str, str]] = {}
123+
for module in _MODULES:
124+
for name, fn in sorted(_pure_status_classifiers(module).items()):
125+
qualname = f"{module.__name__}.{name}"
126+
results: dict[str, str] = {}
127+
for status in VOCAB:
128+
try:
129+
results[status] = fn(status)
130+
except Exception as exc: # the raise itself is part of the contract
131+
results[status] = f"<<RAISED {type(exc).__name__}: {exc}>>"
132+
golden[qualname] = results
133+
134+
GOLDEN_PATH.parent.mkdir(parents=True, exist_ok=True)
135+
GOLDEN_PATH.write_text(json.dumps(golden, indent=2, sort_keys=True) + "\n")
136+
137+
print(f"vocab inputs: {len(VOCAB)}")
138+
print(f"classifiers captured: {len(golden)}")
139+
for qualname in sorted(golden):
140+
print(f" {qualname}")
141+
print(f"golden -> {GOLDEN_PATH.relative_to(REPO)}")
142+
143+
144+
if __name__ == "__main__":
145+
main()

0 commit comments

Comments
 (0)