Skip to content

K2GO-391 feat(app-backstop): active user report when the disk guard contains a problem - #552

Merged
luisguzman-adfa merged 2 commits into
mainfrom
feat/K2GO-391-disk-guard-report
Sep 5, 2026
Merged

K2GO-391 feat(app-backstop): active user report when the disk guard contains a problem#552
luisguzman-adfa merged 2 commits into
mainfrom
feat/K2GO-391-disk-guard-report

Conversation

@luisguzman-adfa

Copy link
Copy Markdown
Collaborator

What

The active report channel for the disk guard, plus its localization. When the
guard handles a meaningful situation, it tells the user and offers a report the
user sends via email -- not only the automatic GlitchTip report. The report is
self-diagnosing and bounded.

Why

The operator should understand what the guardian did and raise it in one tap,
without knowing internals. Developers get a real field report actively, not only
by waiting on GlitchTip. And the report can never grow large enough to break the
reporting pipe.

How

The guard runs in WatchdogService (no Activity) and the email flow needs one, so
notifyUser posts a notification whose tap opens LibraryActivity with a pre-filled
diagnostic (EXTRA_DISK_GUARD_REPORT). LibraryActivity.onResume hands it to
FeedbackFab.sendFeedback(..., FeedbackType.BUG, msg) -- the ADFA-5119 pre-filled
pattern -- and consumes the extra so it never re-fires. Fires on the escalation
and a recurring-firehose contain only (routine low-disk reap does not notify);
distinct notification ids per kind.

The report is self-diagnosing and bounded, in both the email and the automatic
GlitchTip event:

  • source (low_disk | firehose_signal | debug), so trip_or_streak reads correctly
    (a debug run is -1, a real firehose is its server streak).
  • firehose_paths -- which log was the culprit -- parsed from the endpoint and
    capped in count and length (FirehoseSignalSource); never log content. The
    runaway log stays on the device.
  • The only attachment is the feedback screenshot (~100 KB), so a runaway log can
    never bloat the report and break the email/Sentry pipe.

Authority: ADR-386 sections 7 and 12.

l10n

The disk-guard alert strings shipped parked in strings_untranslated.xml. They are
now migrated to a translated per-feature file: values/strings_diskguard.xml plus a
per-locale file for all 33 locales. Translations are machine-generated, marked for
human review in each file header ("K2Go" kept as a product name). The tracking
file is now empty.

Verification

Compiles clean; two-pass review applied (fixed a stale Javadoc and a
notification-id collision; the report path is bounded by design). Domain tests
green (DiskGuardEscalation 5, DiskGuardPolicy 4, FirehoseSignal 6).
./gradlew :app:lintDebug BUILD SUCCESSFUL (MissingTranslation clean). Device-
verified end to end on a OnePlus 7T (HD1901): the debug firehose hook with a
growing .log posted the notification; tapping it opened LibraryActivity and
composed the pre-filled feedback email (subject "[K2Go] Bug -- disk-guard", body
with the full envelope plus source/action/reaped/reclaimed_bytes/trip_or_streak/
free_bytes), with the screenshot attached. The box reaped and relaunched
(restart-to-keep-alive).

…ontains a problem

The disk guard already reports to GlitchTip automatically. This adds the ACTIVE
channel: when the guard handles a meaningful situation, it tells the user and
offers a report the user sends via email -- not only waiting on GlitchTip.

The guard runs in WatchdogService (no Activity), and the feedback email needs
one. So notifyUser posts a notification whose tap opens LibraryActivity carrying
a pre-filled diagnostic (EXTRA_DISK_GUARD_REPORT); LibraryActivity.onResume hands
it to the existing feedback flow (FeedbackFab.sendFeedback, FeedbackType.BUG),
the same pre-filled pattern the install-failed report uses (ADFA-5119). The extra
is consumed on first resume so it never re-fires.

Fired on a meaningful containment only: the escalation (box stopped) and a
recurring-firehose contain. The routine low-disk reap does not notify (no nag);
it is still recorded to GlitchTip. Each event kind uses its own notification id
so one does not replace the other. Diagnostic carries action, reaped, reclaimed
bytes, trip/streak and current free bytes; the feedback flow adds the standard
envelope (version, device, ABI). New strings in strings_untranslated.xml.

Authority: controller/docs/ADR-386-unattended-disk-containment.md section 12.
…e + firehose paths)

Make the report self-diagnosing without the session context, and keep it from
ever carrying raw logs.

- source field (low_disk | firehose_signal | debug) in both channels (Sentry +
  email). It disambiguates trip_or_streak: a debug run reads -1, a real firehose
  reads its server streak, a low-disk trip reads its count. No more cryptic -1.
- firehose_paths: which log(s) were the culprit. FirehoseSignal now parses the
  paths the endpoint already returns; FirehoseSignalSource caps them (count and
  length), so a pathological signal cannot bloat the report.
- Bounded by design: the report is a pointer plus a short summary, never log
  content. The firehose log stays on the device; the only attachment is the
  feedback screenshot (~100 KB). So a runaway log can never break the email/Sentry
  pipe. Documented in ADR-386 section 7 ("bounded by design").

formatPaths is the one shared path formatter (report + email). FirehoseSignalTest
gains a paths case (null -> empty). Domain tests green (Escalation 5, Policy 4,
FirehoseSignal 6).
@luisguzman-adfa
luisguzman-adfa merged commit e77b640 into main Sep 5, 2026
3 checks passed
@luisguzman-adfa
luisguzman-adfa deleted the feat/K2GO-391-disk-guard-report branch September 5, 2026 22:13
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