Repository navigation
validator: report each miner's evaluation stage to the server as it runs - #179
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
The validator now tells the server where each miner is in its evaluation, so the Submissions page drawer can show it live. Nothing it sends carries a score of any kind: no pool scores, lower bounds, points, eligibility, item ids, item content or counts that depend on hidden set outcomes. It sends only a stage name, a done and total count against the arena's published pool size, and a refusal reason.
Stages, in order:
queued,fetching,checking,slm,harness,escalation,system,scoring,sent,refused.Wire
POST /v2/reports/progress, signed exactly likePOST /v2/reports/artifact(same_request(..., signed=True)path, so the same hotkey, timestamp and signature headers and the same nonce). Body:{"arena_id": "...", "epoch_index": 12, "miner": "5F...", "stage": "slm", "done": 14, "total": 40, "note": ""}noteis only filled forrefusedand is cut to 300 characters.totalis never belowdone.Reporter (
validator/progress.py)done == total) always go out.run_epochwithenabled=not config.dry_run, so a dry run posts nothing, and handed toset_up_baselines. TheRunnerdefault is a disabled reporter, so anything building aRunnerdirectly is unaffected.Runner.close()closes the reporter; the worker drains what is queued and exits. If the queue or the baseline setup fails,run_epochcloses the reporter and raises as before.Totals are published pool sizes
Every pool reports against
EpochContext.pool_size(test), the arena definition'sitem_countsentry for that test (the counts the server cuts each batch with), falling back to the number of original items only when the definition has none. ATallytakes that total plus the number of steps the loop really runs and scalesdoneonto the total, sodonereachestotalexactly when the pool ends and never reflects how many items a hidden outcome selected.doneby its share, so the pool still ends attotal.Hooks (
validator/epoch.py,validator/collect.py)run_epochbuilds the queue right afterload_contextand postsqueued(done = position + 1,total = queue length) for every queued miner andrefusedwith the reason for every refused hotkey on the roster, beforeset_up_baselinespulls images, downloads bases, starts the probe agent and runs the reference. The same queue then feedsminer_loop.fetch_and_check:fetchingbefore the artifact download.collect.materialisetakes anon_downloadedcallback, called once the artifact repository is on disk and before the manifest is read, which postschecking. The stage stayscheckingthrough the SLM repository download and checks, the weights digest, turn order and the duplicate claim.slm_phasepostsslmat(0, total)before the SLM sandbox opens, so model loading shows underslm.progresscallback, called with(done, total). TheTallywraps the loop's iterable, so the loop bodies (including theircontinuebranches) are unchanged.scoringbeforescore_miner, thensentonce the signed result is accepted, orrefusedwith the failure as the note. This lives inpost_result, so the close time retry reports too.Hot copy into a running validator
The image installs the package in editable mode at
/opt/microtensor, so copying these and restarting the container is enough:microtensor_subnet/validator/progress.py(new)microtensor_subnet/validator/client.pymicrotensor_subnet/validator/collect.pymicrotensor_subnet/validator/context.pymicrotensor_subnet/validator/epoch.pymicrotensor_subnet/validator/pools/slm.pymicrotensor_subnet/validator/pools/harness.pymicrotensor_subnet/validator/pools/escalation.pymicrotensor_subnet/validator/pools/system.pycollect.pyon this branch already carries #180 and readscontract.SUBMISSION_LICENCE, so a container built before #180 also needsmicrotensor_subnet/artifact/contract.pyfrom main, and one built before #178 also needsmicrotensor_subnet/artifact/validate.py.Until the server route ships, posts get a 404 or 405 and are dropped at debug level, so this is safe to roll out first.
Checks
ruff check, ruff format and mypy are clean; the local suite passes, with four focused local tests for the scaled tally, the throttle, the stage sequence through the miner loop and
queuedgoing out before the baseline setup.🤖 Generated with Claude Code