Direct answer
A trustworthy model-download indicator reports only what the client has actually observed. Define the artifact identity and the source of the expected byte count; count bytes written for the current transfer; represent an unknown denominator as indeterminate; and keep transfer completion separate from integrity verification, runtime loading, and offline task readiness. Never turn a percentage into a promise about remaining time unless you have a validated estimator for that exact transfer context. HTTP response metadata describes a representation and a response, not automatically the final artifact expected by the application. If a resumed request receives a full response instead of a valid partial response, the client must not append it to the old partial file. If the expected length is a placeholder or the server omits Content-Length, the interface should say that progress is being measured without pretending to know total completion. This distinction matters because download progress is one stage in a longer delivery state machine. A user may see all expected bytes arrive, but a configured digest may still be absent, a digest check may still fail, the final file may not yet be installed, and the runtime may still reject it. In the repository's current ModelDownloader, the transfer emits bytes and a total, writes a temporary file, may verify SHA-256 if a value is configured, then attempts to rename the temporary file and emits Completed. The current Gemma E2B SHA-256 field is empty; therefore the implementation can skip digest verification for that configuration. A product screen must not describe the observed 100% transfer state as cryptographic verification or proof of a successfully loaded model. The progress denominator must be tied to a named source. It could come from a pinned manifest, a validated response length, or a documented known-length asset. Record which source was used and whether a response is full or partial. On a partial response, the Content-Length generally describes the range body, not necessarily the whole artifact, so derive a total only when the requested byte offset and response range metadata agree. A stale or invalid temporary file makes the local offset suspect. A redirect, proxy, or captive portal can also change the response body; status and content type should be checked before bytes are credited as model bytes. Do not infer a total from a filename, a rounded marketing size, or a previous version. Avoid displaying a precise time estimate from a single recent speed sample. Mobile transfer rate can vary with network changes, radio state, server throttling, and other activity. If the product has not validated an estimator, show bytes transferred, an honest indeterminate state, and controls to pause or cancel. If a range resumes, clarify whether the displayed count includes previously persisted bytes or only the current session. This avoids a progress bar moving backward or appearing complete when the active representation has changed. For a new artifact revision, reset the old byte count rather than carrying it across versions. Use these implementation stages as separate observable states: queued or awaiting constraints; connecting; receiving; paused or stopped; transfer finished; verifying; installing; loading; ready; and failed with a recoverable category. A UI may combine some states visually, but logs and tests should preserve them. If a worker is cancelled or stopped, its state must not be presented as completed. If a notification is disabled, the worker state remains authoritative; notification visibility is not a transfer signal. If a user closes the screen, progress ownership should not depend on that screen remaining alive. For each run, capture a privacy-safe record: artifact key and revision, expected-length source, HTTP status class, partial/full response classification, persisted byte offset, newly written byte count, verification state, install result, and cancellation or failure class. Avoid raw user prompts, transcripts, credentials, or full download URLs containing sensitive tokens. Compare the recorded transfer with the UI at boundaries such as zero bytes, an unknown total, a valid partial response, a server returning a full response, a changed artifact revision, verification failure, and successful install. The purpose is not to claim a certain download speed; it is to prove the UI accurately communicates state. ### Procedure 1. Freeze the artifact identity and denominator. Record the immutable revision, expected byte count and its authoritative source, plus whether the count is measured, published, or still a placeholder. If no trustworthy total exists, choose an indeterminate UI. 2. Define response accounting. For each HTTP response, record status, range metadata, content length, final representation identity, and the local partial offset. Credit bytes only after the response is classified; never append an ordinary full response to a partial file. 3. Model transfer and post-transfer states independently. Test receiving, stop, resume, cancellation, transfer finished, verification, install, load, and ready. A progress value of 100% must not skip later states. 4. Compare UI to a deterministic fixture matrix. Exercise unknown length, valid partial response, ignored range, changed revision, duplicate observers, activity recreation, and digest mismatch. Assert both the visible label and the underlying state. 5. Review user controls and diagnostics. Ensure cancellation is observable, retry preserves only valid partial data, notifications are not the source of truth, and diagnostic output excludes content and secrets. ### Acceptance criteria - The denominator has a named source and the UI becomes indeterminate when that source is absent or untrusted. - Full and partial responses cannot be confused; bytes from an unvalidated representation are never credited or appended. - Transfer finished, verification passed, installed, runtime loaded, and offline-ready are distinct states in tests and user-facing copy. - Cancellation, activity recreation, and worker observation do not fabricate completion or reset authoritative progress. ### Comparison | Signal | What it establishes | What it does not establish | |---|---|---| | Bytes written | A measured amount reached the temporary file | Correct artifact identity, integrity, or loadability | | Expected byte count | A denominator from the recorded manifest or response policy | That the server delivered the expected representation | | Verification and load states | Separate checks reported by the implementation | General compatibility or performance on other devices | ### FAQ **Can the progress bar say 100% when the final byte arrives?** It can show transfer completion, but label the following verification and installation states separately. If the product uses one bar, keep a visible phase label so the user is not told the model is ready before checks finish. **What should happen when Content-Length is missing?** Use an indeterminate progress presentation, report bytes received if useful, and avoid inventing a denominator or completion time. A later manifest or verified length can establish a total, but the UI should say which source supplies it. **Can I show remaining minutes based on the current rate?** Only if you have validated that estimator against the relevant transfer conditions and explain its uncertainty. Otherwise a changing mobile rate makes a precise estimate misleading; elapsed time and bytes are safer facts. **Does a completed download mean offline use is ready?** No. Verification, installation, runtime initialization, required companion assets, and a representative no-network task are separate checks. Define readiness from the actual feature requirements and test the complete path.
A transfer reaches its displayed limit before verification finishes
A traveler begins downloading an optional model before a trip. The screen reaches a full progress bar, but the app still has a digest step, a file promotion step, and a runtime-load step. A second run may resume from a temporary file, while the server can respond differently to the Range request.
Decision
Keep byte transfer, response validation, integrity, installation, loading, and readiness distinct. Use an indeterminate state whenever the current response cannot support a trustworthy denominator.
Expected outcome
The user sees exactly which stage is complete and can decide whether to wait, cancel, retry, or use a fallback without being told that an unverified file is ready.
Evidence to collect
The claim becomes reviewable only when the following evidence is attached to the same artifact and test run:
- Expected length source
- Transferred bytes
- Verification phase state
A completed byte stream is not enough. Final placement, integrity, runtime load, and recovery must also pass.
Implementation workflow
- Name and verify the progress denominator. Bind the total to an immutable artifact manifest or a validated response policy. Store the source and revision beside the number. When the configuration contains a placeholder or the response omits a trustworthy total, render an indeterminate state rather than borrowing a value from another model revision.
- Classify each full or partial response. Record response status, range metadata, body length, final representation identity, and the partial-file offset. For a resume, accept only a response that proves the requested range is being returned for the same artifact. A full response must replace or restart the temporary representation; it must never be appended after prior bytes.
- Separate transfer from validation and readiness. Emit explicit transitions for bytes received, transfer finished, digest verification, final-path promotion, runtime load, and task readiness. If no trusted SHA-256 is configured, say verification was not performed rather than implying a check passed. Preserve the last completed stage on failure.
- Exercise lifecycle and observer cases. Test screen recreation, duplicate progress observers, worker stop and resume, cancellation, and notification denial. The background owner must remain authoritative; a detached UI collector must not cause completion or erase progress.
- Audit the displayed claim and diagnostic record. Compare every label with the underlying state and create privacy-safe event fields for artifact revision, response type, byte counts, verification and install outcomes. Exclude private user content, authorization headers, and sensitive query parameters from logs.
Keep each transition observable. A failure should identify the stage, artifact, runtime, and recovery action without logging private user content.
Acceptance criteria
- Unknown or placeholder totals never produce a fabricated percentage or remaining-time promise.
- Range metadata and artifact identity are checked before resumed bytes are appended or credited.
- The screen and state model distinguish transferred, verified, installed, loaded, and offline-ready.
- Cancellation, observer recreation, and notification settings cannot turn an incomplete transfer into a success state.
Decision table
| Dimension | Choice or evidence | How to interpret it |
|---|---|---|
| Byte counter | Observed file output | Useful for progress but does not certify provenance or file integrity. |
| Manifest or response total | Progress denominator | Valid only when bound to the exact artifact representation and response semantics. |
| Verification and load result | Post-transfer readiness evidence | Must follow transfer; it should not be inferred from a full progress bar. |
Failure patterns to prevent
- Showing 100% before integrity checks
- Inventing time remaining
Also prevent silent fallback, unpinned artifacts, missing cancellation, and conclusions that combine unlike configurations. Store unsuccessful runs alongside successful ones.
Minimum reproducibility record
| Layer | Record |
|---|---|
| Device | Manufacturer, model, chipset, RAM class, operating-system build |
| Software | Application version and git commit |
| Model | Family, variant, revision, format, file length, hash, quantization |
| Runtime | Name, revision, requested backend, observed backend evidence |
| Workload | Fixture revision, input hash, prompt hash, output policy |
| Outcome | Completed, failed, cancelled, fallback, and privacy-safe diagnostics |
Release checklist
- ☐ The primary query is answered without an unsupported number.
- ☐ Every artifact and runtime is pinned.
- ☐ The representative task and failure policy are explicit.
- ☐ Lifecycle, cancellation, cleanup, and fallback are tested.
- ☐ User-content and network boundaries are documented.
- ☐ Result wording applies only to the recorded configuration.
- ☐ The page links to raw method or evidence when results are added.
Sources and related evidence
- Cove Gemma 4 model page
- IETF HTTP Semantics (range requests and representation metadata)
- Android WorkManager: manage and observe work
- Android WorkManager persistent work
Chinese deployment and troubleshooting content is organized in the .奇连 AI 端侧专题.
Frequently asked questions
Can a full progress bar mean the model is ready?
Only if the interface clearly labels that it means transfer finished. Verification, installation, runtime loading, and the required offline task may still fail, so use separate phases or labels.
What if the server does not provide a total length?
Use an indeterminate state and, if helpful, show observed bytes. Do not substitute a family estimate or a prior artifact size; record the missing denominator and continue only under an explicit policy.
Should the app estimate time remaining?
Avoid precise remaining-time promises without a validated estimator for the relevant network and transfer conditions. Mobile rates fluctuate, so bytes and phase labels are more defensible.
Does 100 percent prove file integrity?
No. It describes a byte-count relationship only. A trusted digest or another clearly documented validation must run separately, and the result should state whether that check was available and passed.