docs(sync): record operational private rollout

This commit is contained in:
fy59 2026-09-17 17:24:55 +02:00
parent e64ea836f7
commit 56ac1cdfd2
9 changed files with 165 additions and 30 deletions

View file

@ -2,6 +2,18 @@
## Unreleased — 0.1.2
- Completed the authorized private full-generation rollout over production
direct MTP: verified Android and desktop backups, signing-preserving Android
updates, schema migrations, persistent peer pairing, bidirectional durable
ACKs, restart and idempotent replay. This did not publish a release or modify
v0.1.1.
- Fixed rollout-discovered feedback idempotence across SQLite row modes,
packaged the complete generation exporter closure, ignored stale Android
coordination objects until their run/generation correlation matches, and
made the Android screen report completed generation conversations instead of
waiting for a legacy receipt.
- Packaged `trainlog-sync-once` and `trainlog-syncd` with the relocatable sync
candidate so user services cannot mix a versioned install with live-checkout
helpers during rollout.

View file

@ -91,6 +91,16 @@ Android and the TUI in each stable release share the same Trainlog product
version on both mirrors. Database schemas and JSON protocol versions are
independent.
### Daily synchronization on an opted-in installation
Connect and unlock the paired phone, keep Trainlog's Synchronization screen in
the foreground, then select **Synchronize** in the local Web Dashboard and
**Synchronize now** on Android. Wait until Web reports completion and Android
shows that synchronization completed on both Android and PC. A failure remains
durable and should be diagnosed before retrying; do not delete generation,
ACK, database, or backup files. Full-generation mode is a trusted local opt-in;
other installations continue to use the established V3 request/receipt path.
### Build from source
Desktop:

View file

@ -956,3 +956,11 @@ The installed schema-v17 release has no backup UI. The reproducible
adds only the backup surface, assigns a higher candidate version code and
builds/tests an APK without installing it. Its synthetic v17 archive is also
restored by current code and migrated through the normal v17-to-v20 path.
The authorized private rollout used the bridge only to add the backup surface
without clearing package data, verified the resulting plaintext archive, then
installed the current signed release variant through a strictly increasing
version-code chain. The final installed private candidate retains product
version 0.1.2 and schema v20. Its full-generation foreground coordinator waits
for correlated objects, tolerates stale objects left by interrupted runs, and
shows completion only after both durable peer acknowledgements.

View file

@ -1,12 +1,13 @@
# Current implementation state
The development branch has opt-in full-generation coordination with durable Web
progress and a foreground Android conversation. Its production generation MTP
adapter is integrated and tested through an object-I/O boundary double. Android
also has a complete same-installation backup/verify/restore container, and a
non-installed schema-v17 bridge candidate is reproducibly built and tested.
Physical-device MTP, release signing, real user backup/restore, main integration
and deployment are not complete.
The opt-in full-generation path is operational on the private daily
installation. The loopback Web control and foreground Android coordinator use
the production direct-libmtp adapter, correlated manifest/ACK V1 objects, and
persistent peer identities. The controlled rollout verified real backups, the
schema-v17 to v20 Android update chain, desktop v18 to v21 migration, three
complete hardware conversations, restart, and idempotent replay. Drive was not
configured and remains outside this local MTP result. This is a private 0.1.2
development deployment, not a public release; v0.1.1 is unchanged.
`TRAINLOG_NATIVE_BUILD_AND_CANDIDATE_V1` closes the native warning gate. Strict
GCC 16.2.1 and Clang 22.1.8 builds now pass the same 81-test inventory, and the
@ -75,6 +76,7 @@ parallel implementation of its rules.
| Web sync API V1 | `TRAINLOG_WEB_SYNC_API_V1=PASS/FROZEN` |
| Web sync button V1 | `TRAINLOG_WEB_SYNC_BUTTON_V1=PASS/FROZEN` |
| Sync Web end-to-end wrapper | `TRAINLOG_SYNC_WEB_END_TO_END_V1=PASS/FROZEN` (isolated) |
| Private full-generation rollout | `TRAINLOG_SYNC_FINALIZATION_AND_ROLLOUT_V1=PASS` (direct MTP, one authorized phone) |
| Local Web | `TRAINLOG_WEB_V1=CONTRACT_FROZEN / IMPLEMENTATION_STARTED` |
| Complete synchronization gap contract | `TRAINLOG_SYNC_GAP_CONTRACT_V1=CONTRACT_FROZEN / IMPLEMENTATION_IN_PROGRESS` |
| Isolated synchronization test environment | `TRAINLOG_SYNC_TEST_ENV_V1=PASS/FROZEN` |

View file

@ -0,0 +1,67 @@
# Full-generation synchronization V1 private deployment record
Date: 2026-09-17
Status: `TRAINLOG_SYNC_FINALIZATION_AND_ROLLOUT_V1=PASS`
This record deliberately omits phone serials, peer IDs, generation IDs,
credential locations, user content, and private backup hashes. Complete causal
evidence is retained in the private rollout journal.
## Installed set
- Trainlog 0.1.2 development; desktop schema v21 and Android schema v20.
- Versioned relocatable desktop bundle behind stable user-bin symlinks.
- Android release-variant APK installed only through compatible signed updates;
the final private rollout version code is 6.
- Production direct-libmtp generation adapter with one explicitly paired peer.
- Loopback Web service and the user-session request daemon are active from the
same versioned installation. No live-checkout runtime helper is used.
## Data and migration evidence
- The original Android schema-v17 store was backed up through the signed bridge
UI and verified for manifest, digests, SQLite integrity, foreign keys and an
exact semantic match to the pre-update store. The real archive migrated on a
copy before live installation.
- A post-migration Android backup was also verified. The real source contained
no active draft, so draft restoration was correctly not applicable; no
synthetic draft was inserted.
- The desktop schema-v18 store was copied with SQLite's backup API, validated,
and migrated on an isolated copy before the live schema-v21 open. Historical
table values were preserved.
- Backups, failed generations, rejection ACKs and successful generation/ACK
evidence remain retained. No one-sided rollback was performed after causal
writes began.
## Operational evidence
- The actual foreground Android advertisement exposed the required persistent
identity and all five capabilities.
- Production libudev/libmtp discovery and object transfer completed on the
selected unlocked phone.
- Three final bidirectional conversations completed with a durable consumed ACK
on each peer and all eight required domains reported successful.
- A service/application restart and a second non-destructive exchange produced
no duplicate business data. Logical hashes for 23 desktop business tables
and 540 rows were identical before and after replay; integrity and foreign-key
checks passed.
- Android visibly returned to an enabled action and displayed synchronization
completion for both Android and PC.
## Rollout repairs
The real rollout exposed and closed four bounded defects: feedback idempotence
depended on the SQLite row representation; the desktop package omitted several
runtime exporters; Android accepted stale coordination filenames without
run/generation correlation; and its UI waited for a legacy receipt after the
generation coordinator had already completed. Regression tests cover each
affected boundary.
## Remaining limits
The phone must be connected, unlocked and in the foreground synchronization
flow. Retained outgoing generations remain subject to the explicit capacity of
eight per peer; evidence is never silently evicted. Drive was not configured or
tested. This private deployment does not publish 0.1.2, create a tag or release,
or alter the existing v0.1.1 release.

View file

@ -1,9 +1,9 @@
# Roadmap
Before controlled rollout, complete and validate the physical libmtp generation
adapter, establish a legitimate installed-Android backup path, verify release
signing continuity and obtain explicit rollout approval. Do not enable generation
mode or advance `main` before those gates.
The controlled private rollout is complete for the paired daily installation:
physical libmtp, verified backups, signing continuity, migrations, correlated
ACKs, restart, and idempotent replay passed. Generation mode remains an
explicit per-installation opt-in; Drive is still unconfigured and unvalidated.
This document owns future work. The implemented baseline is summarized in
[current_state.md](current_state.md); completed narratives and evidence belong
@ -38,7 +38,7 @@ visualizations are implemented; the other four Web routes remain placeholders.
## Current cursor
```text
CURRENT_OPERATIONAL_CURSOR=TRAINLOG_SYNC_DEPLOYMENT_READINESS_V1
CURRENT_OPERATIONAL_CURSOR=TRAINLOG_WEB_V1_NEXT_CONTRACT
```
The focused `TRAINLOG_SYNC_CAUSAL_DELETE_V1_CLOSEOUT` is complete before this
@ -47,9 +47,10 @@ cross-platform draft revision identity and resource-bound admission are closed.
`TRAINLOG_SYNC_GENERATION_ACK_V1=PASS/FROZEN`: both platforms expose explicit
coherent capture, immutable manifest publication, whole-generation
transactional consumption, durable correlated ACK and restart/replay entry
points. The orchestrator, Web API and Web control are now complete behind an
explicit trusted opt-in. Automatic V3 selection remains unchanged. The next
boundary is deployment readiness; no rollout starts here.
points. The orchestrator, Web API and Web control are complete behind an
explicit trusted opt-in. The authorized private direct-MTP rollout passed on
real hardware; automatic V3 selection remains unchanged without that opt-in.
The next work returns to separately contracted Web surfaces.
`TRAINLOG_SYNC_GAP_CONTRACT_V1=CONTRACT_FROZEN / IMPLEMENTATION_IN_PROGRESS`
defines the complete-sync target and its bounded dependency order.

View file

@ -776,6 +776,19 @@ idempotently. Causal V1 operation bytes remain unchanged across first emission
and retransmission because generation membership lives only in
`sync_causal_publications`.
The foreground Android coordinator correlates both durable desktop ACKs and
desktop generation references by the active run (and the Android generation
for its ACK). Objects retained from an interrupted conversation are ignored
until atomically replaced by matching objects. After both peer ACKs, Android
reports completion directly; it does not enter the legacy receipt wait state.
The 2026-09-17 private rollout exercised this path with the production libmtp
adapter on one paired Samsung phone. Three complete bidirectional conversations
passed, including service/application restart and an idempotent replay whose
23 desktop business tables and 540 rows retained identical logical hashes.
Rejected pre-fix generations and their ACKs were retained as causal evidence.
No Drive transport was configured or claimed by this validation.
The generation MTP adapter resolves `Documents/Trainlog` through libudev and
libmtp, selects one exact advertised peer/capability set across bounded devices
and storages, and mirrors only bounded regular object names. It downloads to

View file

@ -1,6 +1,17 @@
# Full-generation sync rollout readiness
## Deployment-readiness candidate
## Operational rollout status
`TRAINLOG_SYNC_FINALIZATION_AND_ROLLOUT_V1=PASS` on 2026-09-17 for the
authorized private daily installation. Verified real Android and desktop
backups were retained, migration copies passed before live updates, the signing
identity and increasing Android version-code chain were verified, and the
production libmtp adapter completed bidirectional manifest/ACK conversations.
Restart and idempotent replay also passed. Drive was not configured. No public
release or tag was created, and v0.1.1 was not modified. The sanitized evidence
record is [sync rollout V1 deployment](reviews/sync_rollout_v1_deployment.md).
## Deployment-readiness contract
The generation path remains disabled unless desktop configuration authorizes a
specific persisted Android peer and Android contains the strict opt-in document
@ -10,12 +21,10 @@ bounded typed progress and its descendant process group. The foreground Android
coordinator advertises its real peer identity, publishes manifest-last bytes,
consumes the return generation and emits a durable correlated ACK.
The integrated proof uses the production generation adapter with only its
typed libudev/libmtp I/O callbacks replaced by an object-store double. This is
software evidence for selection, bounds, publication ordering and the complete
conversation, but not evidence for a particular phone's physical libmtp
behavior. Generation mode must remain disabled until that hardware gate and
the separately authorized rollout are complete.
The isolated proof still uses the production generation adapter with only its
typed libudev/libmtp I/O callbacks replaced by an object-store double. The
separate deployment record owns the physical-phone evidence; neither proof
generalizes pairing to another phone or enables generation mode by default.
### Candidate, backup and recovery
@ -54,12 +63,10 @@ the separately authorized rollout are complete.
preserve pending generations, tombstones, finalizations and ACK ledgers; it
must never trigger hidden eviction.
Actual rollout needs one separate approval for the signed APK, desktop bundle,
verified user backups, coordinated service quiescence, pairing, synthetic smoke
and non-destructive hardware smoke. Drive remains separate and untested here.
This is a non-executed rollout checklist. The development branch implements the
path; the daily installation still uses V3.
The grouped rollout approval covered the signed APK, desktop bundle, verified
user backups, coordinated service quiescence, pairing, synthetic smoke and
non-destructive hardware smoke. Those steps are complete for the recorded
private installation. Drive remains separate and untested.
The latest software-only candidate set was rebuilt under the private root
`/home/fy59/.cache/trainlog/sync-rollout-candidate-v1.NEoMDx` from source commit
@ -106,5 +113,6 @@ operator diagnosis; this tranche adds no tombstone or evidence garbage
collection. A migrated database is recovered from its verified backup, never by
assuming an older binary reverses its migration.
Physical MTP, actual Drive configuration, service coordination, installed APK,
main merge and deployment are intentionally not performed here.
The recorded private installation completed physical MTP, service coordination
and APK/desktop deployment. Actual Drive configuration remains untested; the
eight-generation admission bound and foreground-phone requirement remain.

View file

@ -1361,3 +1361,17 @@ SQLite value type and value before restore, migrates through the production
repository owner, and compares that complete historical shape afterward. The
draft assertion follows the archived state instead of requiring the synthetic
fixture's sample draft.
## Private full-generation rollout validation
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
and generation-reference correlation, and the completed-generation UI state.
The real direct-libmtp smoke then completed three bidirectional conversations
on the paired phone. Restart and replay preserved identical logical hashes for
23 desktop business tables and 540 rows; SQLite integrity and foreign-key
checks passed, both outgoing desktop generations were acknowledged, and the
Android UI displayed completion. The private journal retains exact IDs and
hashes. Drive and `connectedDebugAndroidTest` were not run; the personal phone
was used only for non-destructive install, backup and manual sync validation.