Skip to content

K2GO-384 feat(restore): per-pass ETA + stage-granular cancel with damaged-state recovery - #535

Merged
luisguzman-adfa merged 2 commits into
mainfrom
feat/K2GO-384-restore-eta
Sep 4, 2026
Merged

K2GO-384 feat(restore): per-pass ETA + stage-granular cancel with damaged-state recovery#535
luisguzman-adfa merged 2 commits into
mainfrom
feat/K2GO-384-restore-eta

Conversation

@luisguzman-adfa

Copy link
Copy Markdown
Collaborator

Standardizes restore under K2GO-384: honest per-pass progress/ETA, an on-screen
Cancel matched to each pass, and the lifecycle a mid-extract cancel needs.

What changes

Per-pass ETA + honest progress

  • Surfaces the per-pass ETA TarExtractor already computes (it was dropped
    between the extractor and the progress screen), threaded through
    DeepOpState/DeepOpProgressRepository to BackupJobFragment.
  • Fixes the extract-pass progress source: it counted compressed bytes drained
    from the .gz (saturates the moment the pipe empties) instead of members
    written, so the bar froze near 97% and the ETA read "under a min" on a
    multi-minute extract. Now member-based.

Stage-granular Cancel

  • Copy pauses/resumes. Verify (tar -t) is killed and held so "Keep restoring"
    re-runs the check on the same staged temp (no re-copy). Extract is a
    destructive cancel behind a red acknowledgement dialog.
  • The two cancel intents are separate: a safe-zone abort (cancelBeforeExtract)
    can never reach the extract feeder, which reads its own forceExtractCancel;
    both are gated on the service's own phase, not the UI's lagging copy — so a
    confirm racing the verify→extract boundary can't tear the rootfs.
  • A safe-zone cancel is a CANCELLED terminal (on the op state, so it survives
    a config change).

Known-damage recovery lifecycle — see docs/ADR-5343c

  • A force-cancelled (or genuinely failed) extract marks the InstallGuard marker
    DAMAGED — a fourth reading on the one existing marker. isSystemInstalled
    becomes false (box stays down, no reconciler flap on a torn rootfs) and the
    "install in progress" gate lifts, while recovery still owns it via
    isInterrupted. ServerReconcile.desired's no-healthy invariant is kept.

Localization

The 8 new cancel strings are translated into all 33 locales (machine-generated,
flagged for human review).

Verification

  • Device-tested on arm64 (6-case cancel matrix): hold dialogs non-cancelable,
    copy/verify aborts return to the bifurcation with services restarting, and a
    force-cancelled extract settles at desired=DOWN holder=NONE (no flap) with a
    fresh restore no longer blocked.
  • :app:lintDebug green (MissingTranslation satisfied).

Surface the per-pass ETA the extractor already computed but the service
dropped: thread etaSeconds through DeepOpState / DeepOpProgressRepository /
DeepOpService to BackupJobFragment, rendered via the existing EtaText. The
ETA sits on its own line below a full-width bar so it never shrinks the bar
(matches the module-install / maps rows).

Fix the extract pass progress source. It measured compressed bytes READ from
the .gz, which saturates the instant the archive is fully piped into tar --
the bar froze at ~99% and showed a false "under a min" for minutes while tar
was still writing the rootfs to disk. It now tracks members WRITTEN (tar -v,
one line per file), so the bar moves through the write and the ETA reads
honest minutes. VERIFY still counts bytes read (there, reading is the work).

Device-verified on OnePlus 7T: backup -> restore -> clean boot; extract bar
advances through the tail, ETA counts down instead of freezing.
Adds an on-screen Cancel to restore, matched to each pass, and closes the
lifecycle gap a mid-extract cancel exposed.

- Copy pauses/resumes; verify (tar -t) kills + holds so Keep re-runs the
  check on the same temp (no re-copy); extract is a destructive cancel
  behind a red acknowledgement dialog.
- Cancel intents de-aliased: a safe-zone abort (cancelBeforeExtract) can
  never reach the extract feeder, which reads its own forceExtractCancel;
  both gated on the service's own phase, not the UI's lagging copy.
- A force-cancelled or failed extract marks the InstallGuard marker
  DAMAGED (known damage) -> isSystemInstalled=false: the box stays down
  (no flap on a torn rootfs) and the "install in progress" gate lifts,
  while recovery still owns it via isInterrupted. See docs/ADR-5343c.
- A safe-zone cancel is a CANCELLED terminal (survives config change).
- New cancel strings translated to 33 locales (machine, pending review).
@luisguzman-adfa
luisguzman-adfa merged commit a4c57c6 into main Sep 4, 2026
3 checks passed
@luisguzman-adfa
luisguzman-adfa deleted the feat/K2GO-384-restore-eta branch September 4, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant