Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 94 additions & 69 deletions src/operator_trend_closure_forecast_reset_controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8188,85 +8188,110 @@ def _rerererestore_text(text: str) -> str:
return transformed


# Restore-tier depth arithmetic. A restore-tier word is "store"/"stored"/"storing"
# prefixed by one "re" per depth level: restore(1) -> rerestore(2) -> rererestore(3)
# -> rerererestore(4). The translation shims below previously hand-spelled every
# depth-shifted output string; they now share this single primitive, which moves a
# status token's restore tier by `delta` levels (passthrough/unknown tokens carry no
# tier word and are returned unchanged).
_RESTORE_TIER_BASES = ("storing", "stored", "store")


def _shift_restore_tier(token: str, delta: int) -> str:
parts = token.split("-")
for index, part in enumerate(parts):
for base in _RESTORE_TIER_BASES:
if not part.endswith(base):
continue
prefix = part[: -len(base)]
if not prefix or len(prefix) % 2 or prefix != "re" * (len(prefix) // 2):
return token
new_depth = len(prefix) // 2 + delta
if new_depth < 1:
return token
parts[index] = "re" * new_depth + base
return "-".join(parts)
return token


def _translate_restore_tier_status(status: str, *, delta: int, recognized: frozenset[str]) -> str:
# Recognized inputs are translated by shifting their restore tier `delta` levels.
# Passthrough terms (none/blocked/reversing/insufficient-data) are recognized but
# carry no tier word, so the shift returns them unchanged. Anything else -> "none".
if status in recognized:
return _shift_restore_tier(status, delta)
return "none"


_STATUS_TO_RERERESTORE_INPUTS = frozenset(
{
"pending-confirmation-rebuild-reentry-rerererestore",
"pending-clearance-rebuild-reentry-rerererestore",
"rerererestored-confirmation-rebuild-reentry",
"rerererestored-clearance-rebuild-reentry",
"blocked",
"none",
}
)
_PERSISTENCE_TO_RERERESTORE_INPUTS = frozenset(
{
"just-rerererestored",
"holding-confirmation-rebuild-reentry-rerererestore",
"holding-clearance-rebuild-reentry-rerererestore",
"sustained-confirmation-rebuild-reentry-rerererestore",
"sustained-clearance-rebuild-reentry-rerererestore",
"reversing",
"insufficient-data",
"none",
}
)
_REFRESH_TO_RERERESTORE_INPUTS = frozenset(
{
"recovering-confirmation-rebuild-reentry-rererestore-reset",
"recovering-clearance-rebuild-reentry-rererestore-reset",
"rerererestoring-confirmation-rebuild-reentry",
"rerererestoring-clearance-rebuild-reentry",
"reversing",
"blocked",
"none",
}
)
_PERSISTENCE_FROM_RERERESTORE_INPUTS = frozenset(
{
"just-rererestored",
"holding-confirmation-rebuild-reentry-rererestore",
"holding-clearance-rebuild-reentry-rererestore",
"sustained-confirmation-rebuild-reentry-rererestore",
"sustained-clearance-rebuild-reentry-rererestore",
"reversing",
"insufficient-data",
"none",
}
)


def _status_to_rererestore_status(status: str) -> str:
return {
"pending-confirmation-rebuild-reentry-rerererestore": (
"pending-confirmation-rebuild-reentry-rererestore"
),
"pending-clearance-rebuild-reentry-rerererestore": (
"pending-clearance-rebuild-reentry-rererestore"
),
"rerererestored-confirmation-rebuild-reentry": (
"rererestored-confirmation-rebuild-reentry"
),
"rerererestored-clearance-rebuild-reentry": (
"rererestored-clearance-rebuild-reentry"
),
"blocked": "blocked",
"none": "none",
}.get(status, "none")
return _translate_restore_tier_status(
status, delta=-1, recognized=_STATUS_TO_RERERESTORE_INPUTS
)


def _persistence_status_to_rererestore_status(status: str) -> str:
return {
"just-rerererestored": "just-rererestored",
"holding-confirmation-rebuild-reentry-rerererestore": (
"holding-confirmation-rebuild-reentry-rererestore"
),
"holding-clearance-rebuild-reentry-rerererestore": (
"holding-clearance-rebuild-reentry-rererestore"
),
"sustained-confirmation-rebuild-reentry-rerererestore": (
"sustained-confirmation-rebuild-reentry-rererestore"
),
"sustained-clearance-rebuild-reentry-rerererestore": (
"sustained-clearance-rebuild-reentry-rererestore"
),
"reversing": "reversing",
"insufficient-data": "insufficient-data",
"none": "none",
}.get(status, "none")
return _translate_restore_tier_status(
status, delta=-1, recognized=_PERSISTENCE_TO_RERERESTORE_INPUTS
)


def _refresh_status_to_rererestore_refresh_status(status: str) -> str:
return {
"recovering-confirmation-rebuild-reentry-rererestore-reset": (
"recovering-confirmation-rebuild-reentry-rerestore-reset"
),
"recovering-clearance-rebuild-reentry-rererestore-reset": (
"recovering-clearance-rebuild-reentry-rerestore-reset"
),
"rerererestoring-confirmation-rebuild-reentry": (
"rererestoring-confirmation-rebuild-reentry"
),
"rerererestoring-clearance-rebuild-reentry": (
"rererestoring-clearance-rebuild-reentry"
),
"reversing": "reversing",
"blocked": "blocked",
"none": "none",
}.get(status, "none")
return _translate_restore_tier_status(
status, delta=-1, recognized=_REFRESH_TO_RERERESTORE_INPUTS
)


def _persistence_status_from_rererestore_status(status: str) -> str:
return {
"just-rererestored": "just-rerererestored",
"holding-confirmation-rebuild-reentry-rererestore": (
"holding-confirmation-rebuild-reentry-rerererestore"
),
"holding-clearance-rebuild-reentry-rererestore": (
"holding-clearance-rebuild-reentry-rerererestore"
),
"sustained-confirmation-rebuild-reentry-rererestore": (
"sustained-confirmation-rebuild-reentry-rerererestore"
),
"sustained-clearance-rebuild-reentry-rererestore": (
"sustained-clearance-rebuild-reentry-rerererestore"
),
"reversing": "reversing",
"insufficient-data": "insufficient-data",
"none": "none",
}.get(status, "none")
return _translate_restore_tier_status(
status, delta=1, recognized=_PERSISTENCE_FROM_RERERESTORE_INPUTS
)


def _translate_target_for_persistence(target: dict[str, Any]) -> dict[str, Any]:
Expand Down
145 changes: 145 additions & 0 deletions tests/golden/enumerate_recovery_state_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"""Golden-contract enumerator for the operator_resolution_trend restore-tier fractal.

Captures the EXACT current output of every pure ``(status: str) -> str`` classifier
across the full restore-tier status-string vocabulary (depths 1-4), into a golden
JSON file. After the ``recovery_state(target, *, depth)`` collapse, re-run this and
diff the JSON: byte-identical output proves the collapse preserved the contract.

Safety: only imports pure-computation modules (verified free of import-time DB/IO
side effects) and calls pure string classifiers. Never opens a live database.

Run from the repo root: ``uv run python tests/golden/enumerate_recovery_state_contract.py``
"""

from __future__ import annotations

import ast
import inspect
import json
import re
from pathlib import Path
from types import ModuleType

import src.operator_resolution_trend as m_resolution
import src.operator_snapshot_packaging as m_pkg
import src.operator_trend_closure_forecast_reacquisition_controls as m_reacq
import src.operator_trend_closure_forecast_reset_controls as m_reset

REPO = Path(__file__).resolve().parents[2]
GOLDEN_PATH = REPO / "tests" / "golden" / "recovery_state_contract.golden.json"

# The restore-tier axis: depth == number of "re" prefixes on "store".
PREFIXES = ("holding", "pending", "sustained", "recovering")
SIDES = ("clearance", "confirmation")
TIERS = ("restore", "rerestore", "rererestore", "rerererestore")
TIERS_DONE = ("restored", "rerestored", "rererestored", "rerererestored")


def _family_persistence() -> list[str]:
out: list[str] = []
for prefix in PREFIXES:
for side in SIDES:
for tier in TIERS:
base = f"{prefix}-{side}-rebuild-reentry-{tier}"
out.append(f"{base}-reset" if prefix == "recovering" else base)
return out


def _family_done() -> list[str]:
return [f"{tier}-{side}-rebuild-reentry" for tier in TIERS_DONE for side in SIDES]


def _family_just() -> list[str]:
return [f"just-{tier}" for tier in TIERS_DONE]


# Boundary inputs every classifier must still tolerate.
BOUNDARY = (
"none",
"",
"hold",
"reentered-clearance-rebuild",
"reentered-confirmation-rebuild",
"restoring-confirmation-rebuild-reentry",
"restoring-clearance-rebuild-reentry",
)

# Status-token shape: a lowercase, hyphen-joined single token (no spaces). This is
# exactly the form of every dict key / branch literal the classifiers discriminate
# on (e.g. "holding-clearance-rebuild-reentry-rererestore", "insufficient-data",
# "just-restored", "none"). Harvesting these from source guarantees every branch of
# every dict-lookup table is exercised — a golden of all-"none" would be worthless.
_STATUS_TOKEN = re.compile(r"^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$")


def _harvest_status_literals(modules: tuple[ModuleType, ...]) -> set[str]:
harvested: set[str] = set()
for module in modules:
source = Path(inspect.getfile(module)).read_text()
for node in ast.walk(ast.parse(source)):
if isinstance(node, ast.Constant) and isinstance(node.value, str):
value = node.value
if _STATUS_TOKEN.match(value) and len(value) <= 80:
harvested.add(value)
Comment on lines +82 to +83

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Regenerate the harvested golden

With the current tree, rerunning this enumerator no longer reproduces the committed recovery_state_contract.golden.json: the broad literal harvest now picks up the new restore-tier helper literals (re, store, stored, storing), increasing the vocabulary from 265 to 269 inputs and adding rows for every classifier. Please either regenerate and commit the updated golden or filter those non-status implementation literals, otherwise the documented regeneration command always creates an unrelated diff before any behavior change is made.

Useful? React with 👍 / 👎.

return harvested


_MODULES: tuple[ModuleType, ...] = (m_resolution, m_reset, m_reacq, m_pkg)

VOCAB: tuple[str, ...] = tuple(
sorted(
set(_family_persistence())
| set(_family_done())
| set(_family_just())
| set(BOUNDARY)
| _harvest_status_literals(_MODULES)
)
)


def _is_str_annotation(annotation: object) -> bool:
# ``from __future__ import annotations`` makes annotations strings, not types.
return annotation is str or annotation == "str"


def _pure_status_classifiers(module: ModuleType) -> dict[str, object]:
"""Single-parameter ``str -> str`` functions defined in *module* (not imported)."""
found: dict[str, object] = {}
for name, fn in inspect.getmembers(module, inspect.isfunction):
if fn.__module__ != module.__name__:
continue
sig = inspect.signature(fn)
params = list(sig.parameters.values())
if len(params) != 1:
continue
(only,) = params
if _is_str_annotation(only.annotation) and _is_str_annotation(sig.return_annotation):
found[name] = fn
return found


def main() -> None:
golden: dict[str, dict[str, str]] = {}
for module in _MODULES:
for name, fn in sorted(_pure_status_classifiers(module).items()):
qualname = f"{module.__name__}.{name}"
results: dict[str, str] = {}
for status in VOCAB:
try:
results[status] = fn(status)
except Exception as exc: # the raise itself is part of the contract
results[status] = f"<<RAISED {type(exc).__name__}: {exc}>>"
golden[qualname] = results

GOLDEN_PATH.parent.mkdir(parents=True, exist_ok=True)
GOLDEN_PATH.write_text(json.dumps(golden, indent=2, sort_keys=True) + "\n")

print(f"vocab inputs: {len(VOCAB)}")
print(f"classifiers captured: {len(golden)}")
for qualname in sorted(golden):
print(f" {qualname}")
print(f"golden -> {GOLDEN_PATH.relative_to(REPO)}")


if __name__ == "__main__":
main()
Loading