From e1a96f18c0024b8548a39306c073800b9f4d5811 Mon Sep 17 00:00:00 2001 From: sora <2075279110@qq.com> Date: Mon, 14 Sep 2026 03:51:25 +0000 Subject: [PATCH] Scoring phase retargets the same progress bar The bar kept its stale 100% generation state during scoring with only the description counter moving. Now set_scoring() refills the bar with judged samples (0->100%, fresh clock/rate/eta for the phase), clears the generation '+N new' marker, and the next bench retargets back to generating cleanly. Co-Authored-By: Claude --- evalharness/cli.py | 10 +++++++--- evalharness/progress/rich_terminal.py | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/evalharness/cli.py b/evalharness/cli.py index 1064197..7084092 100644 --- a/evalharness/cli.py +++ b/evalharness/cli.py @@ -720,9 +720,13 @@ def _cmd_eval_run(args) -> int: for minutes with zero feedback otherwise (bar sits at 'generating 100%' and looks hung).""" if _reporter is not None: - # live terminal: the bar carries the counter -- log - # lines here are pure noise (21 lines per bench) - _reporter.set_phase(f'scoring {done}/{total_s}') + # live terminal: RETARGET the bar to scoring -- it + # refills 0->100% with judged samples + _ss = getattr(_reporter, 'set_scoring', None) + if _ss is not None: + _ss(done, total_s) + else: + _reporter.set_phase(f'scoring {done}/{total_s}') return # pipes/redirects (no live bar): milestone lines instead, # first completion immediately then every ~10% diff --git a/evalharness/progress/rich_terminal.py b/evalharness/progress/rich_terminal.py index c78d256..ee06ead 100644 --- a/evalharness/progress/rich_terminal.py +++ b/evalharness/progress/rich_terminal.py @@ -123,6 +123,7 @@ class RichTerminalProgress: self.inflight = 0 self.bench_name = description self.restored = max(completed, 0) # checkpoint head start this bench + self._scoring_for = None # next scoring phase retargets anew desc = f'[green]{self.bench_tag}{description} · generating[/green]' if self.task_id is None: self.progress.start() @@ -143,6 +144,29 @@ class RichTerminalProgress: self.heartbeat_task.cancel() self.heartbeat_task = asyncio.create_task(self._heartbeat()) + def set_scoring(self, done: int, total: int): + """Retarget the SAME bar to the scoring phase: generation is finished + and its filled 100% state is stale -- now the bar refills with judged + samples (0% -> 100%), with a fresh clock/eta for this phase.""" + if self.disabled or self.task_id is None: + return + if getattr(self, '_scoring_for', None) != total: + # first callback of this scoring phase: restart the clock, clear + # generation markers (the '+N new' tag is about generating) + self._scoring_for = total + self._last_phase = 'scoring' + self.started = time.monotonic() + self.inflight = 0 + self.restored = 0 + elapsed = max(time.monotonic() - self.started, 1e-6) + self.progress.update( + self.task_id, + description=f'[green]{self.bench_tag}{self.bench_name} · scoring[/green]', + total=total, completed=min(done, total), new='', + rate=f'{done / elapsed:.2f}', inflight=0, cur='0s', + elapsed=_fmt(elapsed), + eta=_fmt((total - done) * elapsed / done) if done and total > done else '-') + def set_bench_tag(self, tag: str): if self.disabled: return