webapp/imaging: bump rewind threshold to stage_index <= 2

Reset trigger previously fired only when a new POST landed at idx <= 1,
which meant a reimage didn't reset the dashboard card until
Run-ShopfloorSetup ran post-PPKG (~10-20 min in). With the WinPE-phase
status push from startnet.cmd in commit 4e018fe firing at idx=2, that
earlier signal needs to count as a new-run marker too.

Threshold of 2 makes startnet.cmd the canonical reset point: within
seconds of PXE menu choice on the bay, the dashboard card flips from
the previous run's high-idx state back to "WinPE: PESetup / WIM apply"
+ fresh started_at.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-05-13 11:29:34 -04:00
parent 6de19fd250
commit e3f523eedd

View File

@@ -66,20 +66,28 @@ def update_session(payload: dict) -> dict:
except (json.JSONDecodeError, OSError):
state = {}
# Reimage detection: if the new payload's stage_index is <= 1 and we have
# an existing session that was further along, treat this as a fresh run.
# Clear log_tail + reset started_at; preserve serial. Without this, a
# reimage on the same bay leaves stale "succeeded" / high-idx state on
# the dashboard until the new run progresses past idx 1.
# Reimage detection: if the new payload's stage_index <= 2 (WinPE startnet
# = 2, Run-ShopfloorSetup start = 1) AND that's lower than the cached
# stage_index, treat as a fresh imaging run on the same bay. Clear
# log_tail + reset started_at; preserve serial; remember the previous
# run's last_updated for audit. Without this, a reimage leaves stale
# "succeeded" / high-idx state visible until the new run progresses
# past idx 2.
#
# Threshold of 2 covers the first signal of a new run: the WinPE-phase
# status push from startnet.cmd at idx=2 (fires within seconds of PXE
# menu choice). Previously the threshold was 1, which meant the reset
# only triggered once Run-ShopfloorSetup ran post-PPKG, ~10-20 minutes
# into a new run.
if state:
try:
old_idx = int(state.get("stage_index") or 0)
new_idx = int(payload.get("stage_index") or 0)
except (TypeError, ValueError):
old_idx, new_idx = 0, 0
rewind = new_idx > 0 and new_idx < old_idx and new_idx <= 1
rewind = new_idx > 0 and new_idx < old_idx and new_idx <= 2
prev_done = state.get("status") in ("succeeded", "failed")
if rewind or (prev_done and new_idx > 0 and new_idx <= 1):
if rewind or (prev_done and new_idx > 0 and new_idx <= 2):
state = {"serial": serial, "previous_run_at": state.get("last_updated"), "log_tail": []}
if not state: