docs(sync): record operational private rollout
This commit is contained in:
parent
e64ea836f7
commit
56ac1cdfd2
9 changed files with 165 additions and 30 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
|
@ -2,6 +2,18 @@
|
||||||
|
|
||||||
## Unreleased — 0.1.2
|
## 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
|
- Packaged `trainlog-sync-once` and `trainlog-syncd` with the relocatable sync
|
||||||
candidate so user services cannot mix a versioned install with live-checkout
|
candidate so user services cannot mix a versioned install with live-checkout
|
||||||
helpers during rollout.
|
helpers during rollout.
|
||||||
|
|
|
||||||
10
README.md
10
README.md
|
|
@ -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
|
version on both mirrors. Database schemas and JSON protocol versions are
|
||||||
independent.
|
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
|
### Build from source
|
||||||
|
|
||||||
Desktop:
|
Desktop:
|
||||||
|
|
|
||||||
|
|
@ -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
|
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
|
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.
|
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.
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
# Current implementation state
|
# Current implementation state
|
||||||
|
|
||||||
The development branch has opt-in full-generation coordination with durable Web
|
The opt-in full-generation path is operational on the private daily
|
||||||
progress and a foreground Android conversation. Its production generation MTP
|
installation. The loopback Web control and foreground Android coordinator use
|
||||||
adapter is integrated and tested through an object-I/O boundary double. Android
|
the production direct-libmtp adapter, correlated manifest/ACK V1 objects, and
|
||||||
also has a complete same-installation backup/verify/restore container, and a
|
persistent peer identities. The controlled rollout verified real backups, the
|
||||||
non-installed schema-v17 bridge candidate is reproducibly built and tested.
|
schema-v17 to v20 Android update chain, desktop v18 to v21 migration, three
|
||||||
Physical-device MTP, release signing, real user backup/restore, main integration
|
complete hardware conversations, restart, and idempotent replay. Drive was not
|
||||||
and deployment are not complete.
|
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
|
`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
|
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 API V1 | `TRAINLOG_WEB_SYNC_API_V1=PASS/FROZEN` |
|
||||||
| Web sync button V1 | `TRAINLOG_WEB_SYNC_BUTTON_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) |
|
| 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` |
|
| Local Web | `TRAINLOG_WEB_V1=CONTRACT_FROZEN / IMPLEMENTATION_STARTED` |
|
||||||
| Complete synchronization gap contract | `TRAINLOG_SYNC_GAP_CONTRACT_V1=CONTRACT_FROZEN / IMPLEMENTATION_IN_PROGRESS` |
|
| 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` |
|
| Isolated synchronization test environment | `TRAINLOG_SYNC_TEST_ENV_V1=PASS/FROZEN` |
|
||||||
|
|
|
||||||
67
docs/reviews/sync_rollout_v1_deployment.md
Normal file
67
docs/reviews/sync_rollout_v1_deployment.md
Normal 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.
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# Roadmap
|
# Roadmap
|
||||||
|
|
||||||
Before controlled rollout, complete and validate the physical libmtp generation
|
The controlled private rollout is complete for the paired daily installation:
|
||||||
adapter, establish a legitimate installed-Android backup path, verify release
|
physical libmtp, verified backups, signing continuity, migrations, correlated
|
||||||
signing continuity and obtain explicit rollout approval. Do not enable generation
|
ACKs, restart, and idempotent replay passed. Generation mode remains an
|
||||||
mode or advance `main` before those gates.
|
explicit per-installation opt-in; Drive is still unconfigured and unvalidated.
|
||||||
|
|
||||||
This document owns future work. The implemented baseline is summarized in
|
This document owns future work. The implemented baseline is summarized in
|
||||||
[current_state.md](current_state.md); completed narratives and evidence belong
|
[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
|
## Current cursor
|
||||||
|
|
||||||
```text
|
```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
|
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
|
`TRAINLOG_SYNC_GENERATION_ACK_V1=PASS/FROZEN`: both platforms expose explicit
|
||||||
coherent capture, immutable manifest publication, whole-generation
|
coherent capture, immutable manifest publication, whole-generation
|
||||||
transactional consumption, durable correlated ACK and restart/replay entry
|
transactional consumption, durable correlated ACK and restart/replay entry
|
||||||
points. The orchestrator, Web API and Web control are now complete behind an
|
points. The orchestrator, Web API and Web control are complete behind an
|
||||||
explicit trusted opt-in. Automatic V3 selection remains unchanged. The next
|
explicit trusted opt-in. The authorized private direct-MTP rollout passed on
|
||||||
boundary is deployment readiness; no rollout starts here.
|
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`
|
`TRAINLOG_SYNC_GAP_CONTRACT_V1=CONTRACT_FROZEN / IMPLEMENTATION_IN_PROGRESS`
|
||||||
defines the complete-sync target and its bounded dependency order.
|
defines the complete-sync target and its bounded dependency order.
|
||||||
|
|
|
||||||
|
|
@ -776,6 +776,19 @@ idempotently. Causal V1 operation bytes remain unchanged across first emission
|
||||||
and retransmission because generation membership lives only in
|
and retransmission because generation membership lives only in
|
||||||
`sync_causal_publications`.
|
`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
|
The generation MTP adapter resolves `Documents/Trainlog` through libudev and
|
||||||
libmtp, selects one exact advertised peer/capability set across bounded devices
|
libmtp, selects one exact advertised peer/capability set across bounded devices
|
||||||
and storages, and mirrors only bounded regular object names. It downloads to
|
and storages, and mirrors only bounded regular object names. It downloads to
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
# Full-generation sync rollout readiness
|
# 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
|
The generation path remains disabled unless desktop configuration authorizes a
|
||||||
specific persisted Android peer and Android contains the strict opt-in document
|
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,
|
coordinator advertises its real peer identity, publishes manifest-last bytes,
|
||||||
consumes the return generation and emits a durable correlated ACK.
|
consumes the return generation and emits a durable correlated ACK.
|
||||||
|
|
||||||
The integrated proof uses the production generation adapter with only its
|
The isolated proof still uses the production generation adapter with only its
|
||||||
typed libudev/libmtp I/O callbacks replaced by an object-store double. This is
|
typed libudev/libmtp I/O callbacks replaced by an object-store double. The
|
||||||
software evidence for selection, bounds, publication ordering and the complete
|
separate deployment record owns the physical-phone evidence; neither proof
|
||||||
conversation, but not evidence for a particular phone's physical libmtp
|
generalizes pairing to another phone or enables generation mode by default.
|
||||||
behavior. Generation mode must remain disabled until that hardware gate and
|
|
||||||
the separately authorized rollout are complete.
|
|
||||||
|
|
||||||
### Candidate, backup and recovery
|
### Candidate, backup and recovery
|
||||||
|
|
||||||
|
|
@ -54,12 +63,10 @@ the separately authorized rollout are complete.
|
||||||
preserve pending generations, tombstones, finalizations and ACK ledgers; it
|
preserve pending generations, tombstones, finalizations and ACK ledgers; it
|
||||||
must never trigger hidden eviction.
|
must never trigger hidden eviction.
|
||||||
|
|
||||||
Actual rollout needs one separate approval for the signed APK, desktop bundle,
|
The grouped rollout approval covered the signed APK, desktop bundle, verified
|
||||||
verified user backups, coordinated service quiescence, pairing, synthetic smoke
|
user backups, coordinated service quiescence, pairing, synthetic smoke and
|
||||||
and non-destructive hardware smoke. Drive remains separate and untested here.
|
non-destructive hardware smoke. Those steps are complete for the recorded
|
||||||
|
private installation. Drive remains separate and untested.
|
||||||
This is a non-executed rollout checklist. The development branch implements the
|
|
||||||
path; the daily installation still uses V3.
|
|
||||||
|
|
||||||
The latest software-only candidate set was rebuilt under the private root
|
The latest software-only candidate set was rebuilt under the private root
|
||||||
`/home/fy59/.cache/trainlog/sync-rollout-candidate-v1.NEoMDx` from source commit
|
`/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
|
collection. A migrated database is recovered from its verified backup, never by
|
||||||
assuming an older binary reverses its migration.
|
assuming an older binary reverses its migration.
|
||||||
|
|
||||||
Physical MTP, actual Drive configuration, service coordination, installed APK,
|
The recorded private installation completed physical MTP, service coordination
|
||||||
main merge and deployment are intentionally not performed here.
|
and APK/desktop deployment. Actual Drive configuration remains untested; the
|
||||||
|
eight-generation admission bound and foreground-phone requirement remain.
|
||||||
|
|
|
||||||
|
|
@ -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
|
repository owner, and compares that complete historical shape afterward. The
|
||||||
draft assertion follows the archived state instead of requiring the synthetic
|
draft assertion follows the archived state instead of requiring the synthetic
|
||||||
fixture's sample draft.
|
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.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue