Skip to content

engine: progressChanged ignores maxIterations/percentComplete changes in the loop-progress snapshot diff #9323

Description

@JSONbored

⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.

Context

progressChanged in packages/loopover-engine/src/loop-progress.ts (~line 79) decides whether a
new ProgressSnapshot differs from the previous one "in a way worth pushing to the customer" —
its own doc comment says it "Compares the displayed axes: phase, status, iteration, and the
activity tail's contents," per #4800's on-change-not-polling design.

ProgressSnapshot (defined ~line 28) has two more displayed fields the function never compares:
maxIterations and percentComplete (computed from iteration / maxIterations, ~lines 45-47).

Concretely: if a caller's maxIterations changes between two snapshots while iteration,
phase, status, and recentActivity all stay the same (e.g. an operator raises the iteration
budget mid-run), percentComplete silently changes value but progressChanged still returns
false — so the customer-facing streaming surface that consumes this (buildProgressSnapshot's
caller in src/api/routes.ts) never pushes the update, and the progress bar shown to the customer
goes stale even though a real, displayed number changed.

test/unit/loop-progress.test.ts has no test exercising a maxIterations-only change between two
snapshots.

Requirements

  • progressChanged must also return true when prev.maxIterations !== next.maxIterations or
    prev.percentComplete !== next.percentComplete, added to its existing OR-chain of comparisons
    alongside phase/status/iteration/activityChanged(...).
  • Do not change activityChanged or the other existing comparisons.
  • Do not change how percentComplete/maxIterations are computed in buildProgressSnapshot
    only the diffing function.

Deliverables

  • progressChanged in packages/loopover-engine/src/loop-progress.ts compares
    maxIterations and percentComplete in addition to its existing four axes.
  • A new test case in test/unit/loop-progress.test.ts asserting progressChanged returns
    true when only maxIterations (and therefore percentComplete) differs between two
    snapshots, with phase/status/iteration/recentActivity held identical.
  • A second new test case asserting progressChanged still returns false when all six axes
    (including the two new ones) are identical between two snapshots — a regression guard
    against over-triggering.

All three deliverables are required in this single PR.

Test Coverage Requirements

This repo enforces 99%+ Codecov patch coverage, branch-counted, on every changed line/branch in
src/**/workers/**. (Note: packages/loopover-engine/src/** is graded under this same gate —
confirm via the repo's Codecov config if adding a new branch here; the two new test cases above
must exercise both the true and false paths of the added condition.)

Expected Outcome

A maxIterations change between two progress snapshots (and the resulting percentComplete
change) is now correctly detected by progressChanged, so the customer-facing streaming surface
pushes the update instead of leaving a stale progress bar.

Links & Resources

  • packages/loopover-engine/src/loop-progress.ts (progressChanged, ~line 79; ProgressSnapshot
    type, ~line 28)
  • src/api/routes.ts (consumer of buildProgressSnapshot/progressChanged, for context)
  • test/unit/loop-progress.test.ts (existing test file to extend)

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions