docs(sync): document MTP visibility guarantees

This commit is contained in:
fy59 2026-09-20 15:30:06 +02:00
parent 0e13c3947a
commit ca2ea9379b
5 changed files with 87 additions and 0 deletions

View file

@ -4,6 +4,19 @@
Development opened after the stable v0.1.2 release.
- Hardened direct-MTP full-generation conversations after a private Android
run was frozen before generation capture. Android now emits bounded
run/phase metadata, refreshes the user-enabled background listener before a
foreground request, and confirms MediaProvider/MTP visibility for immutable
generation objects before publishing their reference. Desktop MTP pulls are
throttled to one complete refresh every three seconds, keep a separate
30-second operation budget, and report expiration of the conversation as a
correlated protocol timeout instead of a misleading final one-second
transport timeout. Explicit requests continue to receive fresh UUIDs.
Mensurations now retains two compact columns at the deployed phone's 312 dp
content width, with a narrow/large-font fallback. Schemas, causal semantics,
generation formats, ACK formats and standalone V3 strictness are unchanged.
- Routed Android foreground and daemon-triggered daily synchronization through
the existing full-generation orchestrator whenever its trusted local
configuration is present. The standalone mobile V3 importer remains strict

View file

@ -1067,6 +1067,28 @@ generation remains resumable only until the desktop generation for that run is
durably consumed; a fully completed run is then excluded from foreground
selection. This preserves late-ACK recovery without replaying completed runs.
The direct-MTP path confirms transport visibility independently from ordinary
`File.exists()` checks. Android fsyncs and atomically commits every immutable
generation artifact, asks MediaProvider to scan those files, waits for all
bounded callbacks, and only then atomically publishes and scans
`android-generation-v1.json`. The same boundary covers the peer advertisement,
explicit request signal, Android consumption ACK and bounded error reference.
Manifest/reference remain the commit markers; scanning does not change their
bytes or protocol meaning. Production logging records only `run_id`, phase,
artifact name, generation ID and result.
When background synchronization is enabled, an explicit UI request refreshes
the foreground listener before starting the UI-owned conversation. The shared
process lock prevents a second run while the UI coordinator is alive; if the
activity is frozen or destroyed, the listener can validate and resume the
durable request without inventing another generation.
The Mensurations grid uses two 140 dp compact fields plus a 10 dp gutter at
normal phone widths. The deployed 1080 px/480 dpi phone supplies approximately
312 dp inside the screen frame and therefore receives two columns. Layouts
below 290 dp, or font scales of 1.5 and above, retain the readable one-column
fallback.
Backup manifests retain format version 1 and the current Android schema. Their
`product_version` is read from installed package metadata, so development
builds record `0.1.3` without a second hard-coded product-version source.

View file

@ -9,6 +9,25 @@ USB listener with mandatory notification and a private-folder Drive grant with
bounded WorkManager checks. Both use the same concurrency-guarded generation
coordinator as SyncScreen.
Direct-MTP publication now has an explicit Android visibility boundary.
Durable immutable generation files are submitted to MediaProvider and all scan
callbacks complete before the mutable generation reference is published; the
reference and Android ACK use the same confirmation. Bounded diagnostic logs
contain only run/generation identities, artifact names, phases and results.
The desktop worker performs lightweight local correlation checks continuously
but opens a full MTP pull no more than once every three seconds. A 30-second
individual adapter budget is distinct from the overall conversation deadline,
so an absent correlated generation reports a protocol wait timeout while an
actually blocked adapter reports `transport_timeout`.
The failed private run `sy_9639f06e-58ba-4bc0-ab1b-1488aefe011c` received its
desktop request and archive-ACK files on the Android filesystem, but created no
Android generation row/reference/object. System evidence shows the activity
was moved to Android's file-access settings and frozen before capture. The
retained Android generation reference and MTP bytes both belonged to an older
run; no hidden new generation was found. No causal or business mutation
occurred.
Existing preparation rows expose separate editing and Android-delivery states
and an accessible send action. Draft/local advances the same preparation to a
ready revision before delivery; ready/local delivers the current revision.

View file

@ -959,6 +959,19 @@ It reads the peer advertisement, current Android generation reference and
current Android consumption ACK, then downloads only the generation directory
named by that validated reference. It does not recursively mirror retained
Android generations, desktop publications, or unrelated exchange history.
Local correlation is checked every 50 ms without USB work; complete MTP pulls
are throttled to a three-second cadence. Each MTP operation has its own
30-second ceiling while the conversation retains its configured global
deadline. Exhausting the global deadline while waiting for a correlated
reference reports `timeout waiting for correlated android-generation-v1.json`;
only an adapter that exceeds its independent operation budget reports
`transport_timeout`.
Android direct-file publication has a separate MediaProvider visibility
barrier. Immutable generation files, including the manifest, become visible
before `android-generation-v1.json` is committed. The reference therefore
cannot advertise a generation whose files have not completed the Android MTP
visibility callbacks. No remote object is removed during polling or scanning.
`GET /api/v1/prepared-items` is a separate read-only Web projection. It does not
change the frozen Dashboard `next_session.available` field or any exchange

View file

@ -1544,6 +1544,26 @@ fixture's sample draft.
## Private full-generation rollout validation
The MTP visibility regression suite uses injected clocks and transport
callbacks, with no multi-second sleeps. It covers delayed Android publication,
multiple throttled polls, stale run references, a never-visible generation,
an independently blocked adapter, and exact protocol-versus-transport timeout
classification. Android tests prove fresh request UUIDs, foreground/background
lock ownership, objects-visible-before-reference ordering, bounded phase
tracing, and a completed full-generation conversation. Compose tests exercise
the measured 312 dp phone content width as two columns, a true 280 dp narrow
layout as one column, 1.5 font-scale fallback, long French labels and `kg`/`cm`
suffixes.
Read-only forensics for failed run
`sy_9639f06e-58ba-4bc0-ab1b-1488aefe011c` found the correlated desktop request
and archive acknowledgements on Android, but no correlated generation
reference, immutable directory or error record. The direct filesystem and MTP
views contained identical bytes for the retained older Android reference.
Logcat showed Android moving Trainlog behind the file-access settings surface
and freezing it before capture. The post-v19 backup predates this run and is
not presented as SQLite evidence for it.
The authorized 2026-09-17 rollout added regression coverage for production
failures found only after installation: feedback import under `sqlite3.Row`,
the complete exporter inventory of the relocatable package, stale Android ACK