Active user attribute set, latest activities, guarded changes to used values, artefact links, durations and averages; irreversible showcase step
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 295952@bnt-lap001 Assistant-Session: e93f64ad-516c-46eb-9666-aad8d300c477
This commit is contained in:
parent
6716cee921
commit
8d62c1fbe8
22 changed files with 1025 additions and 35 deletions
42
rtut/run2.py
42
rtut/run2.py
|
|
@ -56,13 +56,49 @@ def _coerce(run: Run, dp_id: str, value: str) -> tuple[str | None, str | None]:
|
|||
return value, None
|
||||
|
||||
|
||||
def set_datapoint(run: Run, dp_id: str, value: str, how: str = "manual") -> str:
|
||||
"""Give a datapoint a value. Invalid input leaves it in state 'err' (never stores it)."""
|
||||
def datapoint_users(run: Run, dp_id: str) -> list[str]:
|
||||
"""Steps that have already started and use this datapoint: they worked with its current value."""
|
||||
return [sid for sid, s in flow(run).steps.items()
|
||||
if dp_id in s.get("uses", []) and run.data["steps"][sid]["state"] in ("running", "done", "failed", "pushed")]
|
||||
|
||||
|
||||
def changes_needing_override(run: Run, changes: dict[str, str]) -> dict[str, list[str]]:
|
||||
"""Of proposed {datapoint: new value}, those that steps already used and that really change the value."""
|
||||
out = {}
|
||||
for dp, v in changes.items():
|
||||
rec = run.data["datapoints"].get(dp)
|
||||
if rec is None or rec.get("value") is None or str(v) == str(rec["value"]):
|
||||
continue
|
||||
users = datapoint_users(run, dp)
|
||||
if users:
|
||||
out[dp] = users
|
||||
return out
|
||||
|
||||
|
||||
def set_datapoint(run: Run, dp_id: str, value: str, how: str = "manual",
|
||||
override_reason: str = "", acknowledge_risk: bool = False) -> str:
|
||||
"""Give a datapoint a value. Invalid input leaves it in state 'err' (never stores it).
|
||||
|
||||
Changing a value that steps have already used is a deviation: it needs the operator's override
|
||||
(reason and acknowledged risk), only in manual mode, and is recorded as 'changed-after-use'.
|
||||
"""
|
||||
_writable(run)
|
||||
if dp_id not in flow(run).datapoints:
|
||||
raise RunError(f"no such datapoint: {dp_id}")
|
||||
clean, err = _coerce(run, dp_id, value)
|
||||
rec = run.data["datapoints"][dp_id]
|
||||
users = datapoint_users(run, dp_id) if how != "initial" else []
|
||||
if users and rec.get("value") is not None and str(value) != str(rec["value"]):
|
||||
risk = "Steps that already ran used the previous value, so their results may no longer match this one."
|
||||
if run.data["mode"] != "manual":
|
||||
raise RunError(f"{dp_id} was already used by {', '.join(users)}; take over (manual mode) to change it")
|
||||
if not override_reason.strip():
|
||||
raise RunError(f"{dp_id} was already used by {', '.join(users)}. Risk: {risk} "
|
||||
"To change it give a reason and acknowledge the risk; this is recorded as a deviation.")
|
||||
if not acknowledge_risk:
|
||||
raise RunError("changing a value that steps already used needs the operator to acknowledge the risk")
|
||||
_deviate(run, "changed-after-use", dp_id, [f"{s} already used {dp_id} = {rec['value']!r}" for s in users],
|
||||
override_reason, risk, True)
|
||||
clean, err = _coerce(run, dp_id, value)
|
||||
if err:
|
||||
rec.update(state="err", error=err, at=_now())
|
||||
rec.pop("value", None)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue