The weights integrity check still holds a client-side job id: a reload loses a
check in flight. That is the failure mode #492 eliminated for the download, still
present on the other action over the same files. Recorded under "found, not fixed"
in #494; this issue gives it the home the process requires.
cf. #475, #486, #492, #493, #494.
Observed
- Open a
ready local connection's overflow and press Check files are undamaged.
- The row reads
Reading every file… with an n of m files microline.
- Reload, or open the screen in a second tab. The row reads
Ready with the same
menu item offered again, as though nothing were happening. The check is still
reading gigabytes in the worker; nothing on screen says so.
The same is true of a check somebody started from the CLI or from MCP: the
browser has no way to know one is running, because the only thing that ever knew
was the tab that received the 202.
Verified before designing anything
How #493 hung the download off the connection
ConnectionOut.download carries the connection's most recent weight download —
job_id, state, bytes_done, bytes_total, error. It is derived, never
stored: InferenceConnectionService.downloads() reads
JobQueue.list(types={WEIGHT_DOWNLOAD_JOB_TYPE}), which answers newest-first, and
takes the first job per connection id. The job type and the payload key live in
kernel/domain/inference.py because the kernel may not import visionset.jobs
and both sides need one spelling. WeightDownload.of is the single place that
says a job row's processed/total mean bytes for that type.
How #494's frontend polls it
useConnections takes a refetchInterval that is a function of the answer: two
seconds while any row satisfies isDownloading, false otherwise, and false
before the first fetch lands. useDownloadRun holds no job id — it reads
connection.download. Recovery across a reload is then a property of the shape.
How the check reaches the client today — the path being retired
useIntegrityRun (InferenceScreen.tsx) keeps useState<string | null> for a
job id, set from the mutation's onSuccess, and polls useBackgroundJob(jobId).
So only the mount that pressed the item can observe the run. This is the exact
construction #493/#494 removed from the download.
What the check job already reports
check_integrity owns its loop and knows its total before the first file:
on_file(done, len(published)), which jobs/integrity.py already turns into
reporter.report(processed=checked, total=total). The job row therefore already
carries determinate file progress — the wire is the only thing missing. No new
accounting is needed, and the issue's prose-only fallback is not required: a check
gets a real bar, counting files, named as files at the one boundary that knows the
job type.
Shape
A question this pins rather than answers
allowed_actions is not job-aware today, and this issue does not make it so.
CONNECTION_GATES is a pure function of setup state × connection type, so a
connection with a check in flight is still ready and still declares
check_integrity — and still declares download_weights, which is legal in both
states. Nothing in the kernel refuses a second concurrent check or a download
overlapping one.
That is defensible as it stands: the check job is registered idempotent, a second
run reads the same files and reaches the same verdict, and require_checkable
passes at ready precisely so a re-queued orphan and a person asking twice take
the same path. It is also wasteful — two passes over gigabytes — and the
overlap of a download and a check over one cache is a question nobody has
answered.
Making the declaration job-aware would give connection_actions a third
dimension and change what CONNECTION_GATES is. That is a design decision, not a
consequence of putting a check on the wire, so this issue pins today's answer in
a contract test and changes nothing. The screen still disables the control while
its own check runs, which is rendering state and not computing legality.
If a concurrent check or a download-during-check should be refused, that is a
separate issue and Armando's call.
The weights integrity check still holds a client-side job id: a reload loses a
check in flight. That is the failure mode #492 eliminated for the download, still
present on the other action over the same files. Recorded under "found, not fixed"
in #494; this issue gives it the home the process requires.
cf. #475, #486, #492, #493, #494.Observed
readylocal connection's overflow and press Check files are undamaged.Reading every file…with ann of m filesmicroline.Readywith the samemenu item offered again, as though nothing were happening. The check is still
reading gigabytes in the worker; nothing on screen says so.
The same is true of a check somebody started from the CLI or from MCP: the
browser has no way to know one is running, because the only thing that ever knew
was the tab that received the
202.Verified before designing anything
How #493 hung the download off the connection
ConnectionOut.downloadcarries the connection's most recent weight download —job_id,state,bytes_done,bytes_total,error. It is derived, neverstored:
InferenceConnectionService.downloads()readsJobQueue.list(types={WEIGHT_DOWNLOAD_JOB_TYPE}), which answers newest-first, andtakes the first job per connection id. The job type and the payload key live in
kernel/domain/inference.pybecause the kernel may not importvisionset.jobsand both sides need one spelling.
WeightDownload.ofis the single place thatsays a job row's
processed/totalmean bytes for that type.How #494's frontend polls it
useConnectionstakes arefetchIntervalthat is a function of the answer: twoseconds while any row satisfies
isDownloading,falseotherwise, andfalsebefore the first fetch lands.
useDownloadRunholds no job id — it readsconnection.download. Recovery across a reload is then a property of the shape.How the check reaches the client today — the path being retired
useIntegrityRun(InferenceScreen.tsx) keepsuseState<string | null>for ajob id, set from the mutation's
onSuccess, and pollsuseBackgroundJob(jobId).So only the mount that pressed the item can observe the run. This is the exact
construction #493/#494 removed from the download.
What the check job already reports
check_integrityowns its loop and knows its total before the first file:on_file(done, len(published)), whichjobs/integrity.pyalready turns intoreporter.report(processed=checked, total=total). The job row therefore alreadycarries determinate file progress — the wire is the only thing missing. No new
accounting is needed, and the issue's prose-only fallback is not required: a check
gets a real bar, counting files, named as files at the one boundary that knows the
job type.
Shape
through the same discovery mechanism rather than a copy of it. The counts are
named for what they count — a download's are bytes and a check's are files —
because that is exactly the naming boundary feat(inference): a weight download reports its bytes, and the connection carries it #493 established; a shared field
whose meaning depends on a sibling field would be the parallel vocabulary this
is meant to avoid.
ConnectionSetupStatemember, for feat(inference): the Inference screen watches a download instead of owning one #494's reason verbatim: the stateflip is the last statement, so a third member reopens the crash window that
ordering closes and strands a connection there when a worker dies. Liveness is
the job's, and a job settles itself.
stays a job failure carrying prose with no verdict, no purge and no state
change — now simply visible after a reload instead of lost.
the client-side job id path is deleted rather than bypassed.
A question this pins rather than answers
allowed_actionsis not job-aware today, and this issue does not make it so.CONNECTION_GATESis a pure function of setup state × connection type, so aconnection with a check in flight is still
readyand still declarescheck_integrity— and still declaresdownload_weights, which is legal in bothstates. Nothing in the kernel refuses a second concurrent check or a download
overlapping one.
That is defensible as it stands: the check job is registered idempotent, a second
run reads the same files and reaches the same verdict, and
require_checkablepasses at
readyprecisely so a re-queued orphan and a person asking twice takethe same path. It is also wasteful — two passes over gigabytes — and the
overlap of a download and a check over one cache is a question nobody has
answered.
Making the declaration job-aware would give
connection_actionsa thirddimension and change what
CONNECTION_GATESis. That is a design decision, not aconsequence of putting a check on the wire, so this issue pins today's answer in
a contract test and changes nothing. The screen still disables the control while
its own check runs, which is rendering state and not computing legality.
If a concurrent check or a download-during-check should be refused, that is a
separate issue and Armando's call.