179 lines
8.9 KiB
Markdown
179 lines
8.9 KiB
Markdown
# Android session draft v1 — execution and validation record
|
|
|
|
Date: 2026-09-07. **ANDROID_SESSION_DRAFT_V1=PASS.** Implementation, canonical
|
|
documentation synchronization, real-device validation and final audit complete.
|
|
|
|
## Scope and baseline
|
|
|
|
User authorized full execution of `android-session-draft-prompt.md` and selected
|
|
GPT-6 Astra, MEDIUM for substantial implementation. Baseline HEAD: `444a4d2`.
|
|
Existing Notcurses changes were preserved. No staging, commit, push, reset,
|
|
restore, stash, clean, uninstall or package-data clear was performed.
|
|
|
|
## Persistence and review
|
|
|
|
Android local schema migrated additively from v3 to v4. The singleton
|
|
`active_session_draft` and its `draft_session_exercises`,
|
|
`draft_performed_sets`, `draft_continuous_activity` children persist workout
|
|
and raw form state independently of completed history. Repository mutations
|
|
own durable autosave; finalization inserts completed history and clears the
|
|
draft transactionally. Frozen exchange artifacts, desktop schema and timestamp
|
|
semantics are unchanged.
|
|
|
|
The bounded reviewer identified missing selection diagnostics/raw preservation
|
|
and unguarded DB-open/transaction-begin failures. Astra repaired these and added
|
|
regressions. Subsequent bounded review passed the exact repairs and isolated UI
|
|
harness. The missing-selection path clears only the selection, retains every
|
|
raw field and added exercise, and returns a specific warning.
|
|
|
|
## Real-device results
|
|
|
|
Device: Samsung SM_G990B, serial `RFCT10N6ZFP`.
|
|
Both APKs were installed with `adb install -r`; existing installation and
|
|
user data were preserved. The app remains installed and MainActivity was
|
|
launched after validation.
|
|
|
|
The first locked-device UI attempt could not find an interactive Compose
|
|
hierarchy. After the user unlocked the phone, the same installed UI tests
|
|
passed 3/3. Additional cancellation/recreation/idempotency assertions were
|
|
built; the final instrumentation APK then passed **5/5** tests (2 repository,
|
|
3 UI). No keyguard bypass or show-when-locked flags were used.
|
|
|
|
### Production MainActivity matrix
|
|
|
|
- Created a draft through the normal UI using the two existing catalog entries:
|
|
`marche` = 720 seconds at 5.5 km/h; `Gym/Échauffement` = 420 seconds.
|
|
- Home and switching to Android Settings preserved both exact exercises.
|
|
- Back showed Home Resume and the two-exercise summary.
|
|
- Background `am kill` was verified by absent PID; original PID 20863 exited
|
|
and resumed process PID 22891 displayed the exact two-exercise draft.
|
|
- Explicit force-stop and cold relaunch restored Home Resume and exact values.
|
|
- Rotation landscape/portrait caused real `wm_relaunch_resume_activity` events
|
|
for `MainActivity` at 15:16:28 and 15:16:30 device time. Home Resume remained.
|
|
- `lifecycle-two-exercises.db` and `after-lifecycle.db` are byte-identical.
|
|
- Removed `marche` from the draft, leaving `Gym/Échauffement` at 420 seconds.
|
|
Selected `marche` for another unfinished entry, with raw duration `39.`
|
|
and speed `6,`.
|
|
- After verified background process exit and relaunch, Home Resume restored the
|
|
remaining exercise and exact raw fields; the removed exercise was not added
|
|
back. Force-stop/relaunch also restored the raw fields.
|
|
- `removed-with-raw-form.db` and `removed-after-kill-verified.db` are
|
|
byte-identical. Both catalog entries remain present.
|
|
- The normal new-session action opened the existing draft without overwriting
|
|
it. History still displayed no completed sessions.
|
|
- Discard confirmation -> Annuler retained Resume and exact DB bytes
|
|
(`after-discard-cancel.db` matches the raw-form snapshot).
|
|
- Confirmed discard -> force-stop/relaunch left no Resume, and all four draft
|
|
tables had zero rows.
|
|
- The actual mobile snapshot pulled while a draft existed contains zero
|
|
sessions and the unchanged v1 keys: format, version, generated_at, exercises,
|
|
sessions, body_observations.
|
|
- The phone's original 30-second screen timeout and free rotation setting were
|
|
restored after temporary test configuration changes.
|
|
|
|
### Final save and stale-resurrection checks
|
|
|
|
On the same physical device, isolated tests render the production HomeScreen
|
|
and SessionScreen through debug-only, non-exported `DraftUiTestActivity`.
|
|
It uses only `trainlog-draft-ui-test.db` and performs no shared export writes.
|
|
|
|
The production final-save control creates exactly one completed session,
|
|
clears the draft, and returns Home without Resume. Activity recreation still
|
|
shows no Resume and exactly one completed session. A second repository
|
|
finalization returns Invalid and does not create another session. Both host
|
|
and real-SQLite tests cover this repeated-finalization check. Repository export
|
|
contains one completed session after successful finalization.
|
|
|
|
This isolation avoids fictitious completed workouts in the user's real history.
|
|
No actual user completed session was added/deleted for testing.
|
|
|
|
## User-data preservation
|
|
|
|
The original v3 database contained two exercises, one body observation, and no
|
|
completed sessions or session children. Migration and the entire device matrix
|
|
preserved **every original row exactly** across all six original domain tables.
|
|
The final database is v4, integrity check is `ok`, foreign-key check is empty,
|
|
and every draft table is empty. The comparison helper verifies complete rows,
|
|
not merely counts.
|
|
|
|
## Test evidence
|
|
|
|
- Host `./gradlew test`: 8/8 PASS, no skips/failures/errors.
|
|
- `assembleDebug` and `assembleDebugAndroidTest`: PASS.
|
|
- Final device `am instrument`: 5/5 PASS.
|
|
- Desktop Meson compile and suite: 22/22 PASS.
|
|
- Frozen JSON and import-contract validators: PASS.
|
|
- `git diff --check`: PASS.
|
|
- Entire `tui/` compared with pre-ticket tar snapshot: unchanged by this ticket.
|
|
|
|
Host test XML:
|
|
`android/app/build/test-results/testDebugUnitTest/TEST-com.labfytools.trainlog.data.TrainlogRepositoryDraftTest.xml`.
|
|
|
|
Device command:
|
|
|
|
```bash
|
|
adb -s RFCT10N6ZFP shell am instrument -w \
|
|
-e package com.labfytools.trainlog \
|
|
com.labfytools.trainlog.test/androidx.test.runner.AndroidJUnitRunner
|
|
```
|
|
|
|
## Backup and retained artifacts
|
|
|
|
Outside-repository directory: `/tmp/trainlog-android-draft-v1-mD9RFF/`.
|
|
|
|
Original quiescent database/preferences backup: `user-data-before.tar`.
|
|
|
|
SHA-256:
|
|
`3ea2e3b61e921918762a84b88abd82337b7afae25fc2d95ff2420d228fcea980`.
|
|
|
|
Also retained: baseline.patch, baseline-tui.tar, original databases/,
|
|
after-install.db, final-device.db, lifecycle-two-exercises.db,
|
|
after-lifecycle.db, removed-with-raw-form.db, removed-after-kill-verified.db,
|
|
after-discard-cancel.db, export-with-draft.json, completed-device-matrix.db,
|
|
verify_user_data.py and semantic ADB helper device_ui.py.
|
|
|
|
Only `/tmp` was writable outside the repository. The backup must be copied to
|
|
permanent storage before temporary-directory cleanup; no DB backup or generated
|
|
exchange artifact is in the repository.
|
|
|
|
## Final audit and closeout
|
|
|
|
The configured Terra-high `android_final_review` performed the single final
|
|
audit and returned PASS with no blocking findings. It noted that an intended
|
|
post-final-save recreation assertion had landed in the discard test instead.
|
|
The final-save test now also recreates the Activity and rechecks absent Resume
|
|
before verifying exactly one completed session. The corrected test APK was
|
|
installed with `-r`; the entire device suite passed 5/5 again (4.327 seconds).
|
|
|
|
The audit also recorded pre-existing production `MainActivity` repository
|
|
cleanup as non-blocking resource-lifetime maintenance: the helper is not
|
|
explicitly closed on Activity destruction. This was not classified as a new
|
|
durability regression or a prerequisite for this corrective checkpoint.
|
|
|
|
Final normal validation: desktop22/22, JSON21 cases, import6 cases and diff
|
|
check PASS. Android final `test assembleDebug assembleDebugAndroidTest` invocation
|
|
succeeded using retained writable tool homes; its76 tasks were up to date with
|
|
the actual8/8 host run after finalization assertions were strengthened. After
|
|
the last six-line UI-test correction, `assembleDebugAndroidTest` rebuilt
|
|
successfully and the on-device suite passed as recorded above.
|
|
|
|
Sandbox invocation (from `android/`):
|
|
|
|
```bash
|
|
GRADLE_USER_HOME=/tmp/trainlog-gradle-user-home \
|
|
ANDROID_USER_HOME=/tmp/trainlog-android-home \
|
|
JAVA_HOME=/usr/lib/jvm/java-17-openjdk \
|
|
./gradlew test assembleDebug assembleDebugAndroidTest
|
|
```
|
|
|
|
The default Gradle-home invocation initially failed before executing tasks
|
|
because its lock path was read-only; the retained writable homes resolved it.
|
|
SDK analytics and Kotlin-daemon cache paths emitted sandbox diagnostics; Kotlin
|
|
successfully used its fallback compiler. The generated diagnostic log was moved
|
|
outside the repository. No source-warning policy was weakened.
|
|
|
|
Canonical docs are synchronized and PASS markers now reflect executed evidence.
|
|
The original Notcurses implementation is unchanged by this ticket. User data,
|
|
backup, current APKs and full diff/source evidence are retained. No commit or
|
|
push was performed. There is no unfinished implementation or device-validation
|
|
step for this ticket; retain the backup outside temporary storage as noted above.
|