"""Advisory temporal state only; never supplies manipulation completion proof.""" import math,statistics from collections import deque class ProgressMonitor: def __init__(self,run_id,subtask_id,capture_after,max_age=2.,stall_seconds=10.,regression=.15): if not run_id or not subtask_id or any(not math.isfinite(x) for x in (capture_after,max_age,stall_seconds,regression)) or min(max_age,stall_seconds,regression)<=0:raise ValueError('invalid monitor policy') self.run_id=run_id;self.subtask_id=subtask_id;self.capture_after=capture_after;self.max_age=max_age;self.stall_seconds=stall_seconds;self.regression=regression self.sequence=0;self.last_stamp=None;self.samples=deque(maxlen=3);self.peak=None;self.improved=None;self.filtered=None;self.regressions=0;self.last=None def unknown(self,reason):return dict(state='UNKNOWN',reason=reason,completion_authority=False,run_id=self.run_id,subtask_id=self.subtask_id) def update(self,s,now): value=s.get('progress');stamp=s.get('stamp');seq=s.get('sequence') if s.get('run_id')!=self.run_id or s.get('subtask_id')!=self.subtask_id:return self.unknown('identity mismatch') if type(seq) is not int or seq<=self.sequence or type(value) not in (int,float) or not math.isfinite(value) or not 0<=value<=1:return self.unknown('invalid progress/sequence') if type(stamp) not in (int,float) or not math.isfinite(stamp) or not math.isfinite(now) or not self.capture_after<=stamp<=now or now-stamp>self.max_age or (self.last_stamp is not None and stamp<=self.last_stamp):return self.unknown('stale or nonmonotonic observation') if self.last_stamp is not None and stamp-self.last_stamp>self.max_age: self.samples.clear();self.filtered=None;self.peak=None;self.improved=None;self.regressions=0 self.sequence=seq;self.last_stamp=stamp;self.samples.append(value) median=statistics.median(self.samples);self.filtered=median if self.filtered is None else .5*median+.5*self.filtered if self.peak is None or self.filtered>=self.peak+.02:self.peak=self.filtered;self.improved=stamp self.regressions=self.regressions+1 if self.peak-self.filtered>=self.regression else 0 state='REGRESSED' if self.regressions>=2 else 'STALLED' if stamp-self.improved>=self.stall_seconds else 'RUNNING' self.last=dict(state=state,run_id=self.run_id,subtask_id=self.subtask_id,sequence=seq,stamp=stamp,raw_progress=value,progress=self.filtered,hop=s.get('hop'),completion_authority=False) return dict(self.last) def snapshot(self,now): if self.last_stamp is None or nowself.max_age:return self.unknown('feedback unavailable') return dict(self.last)