From 3db84bbfb093d9459dbd29a21b8f21e80318260b Mon Sep 17 00:00:00 2001 From: fy59 Date: Thu, 17 Sep 2026 08:19:18 +0200 Subject: [PATCH] docs(sync): freeze data lifecycle slice --- AGENTS.md | 6 +++--- CHANGELOG.md | 8 ++++++++ README.md | 5 +++-- docs/android.md | 9 +++++++++ docs/architecture.md | 4 +++- docs/current_state.md | 16 ++++++++++++---- docs/database.md | 12 +++++++++--- docs/design/sync_gap_contract_v1.md | 2 +- docs/exchange_format.md | 7 +++++++ docs/roadmap.md | 11 +++++++---- docs/sync_exchange.md | 10 +++++++++- docs/tests.md | 9 +++++++++ 12 files changed, 80 insertions(+), 19 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4e3e481..6e8a0be 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -166,7 +166,7 @@ It is not the canonical analytics store. The Android UI is driven by exercise metadata, never by exercise-name heuristics. -Android local SQLite schema v17 retains the exactly-one durable active-session +Android local SQLite schema v18 retains the exactly-one durable active-session draft introduced in v4. Every meaningful draft/form mutation is persisted by the repository. Back, backgrounding and process death never delete the draft. Home offers explicit @@ -180,7 +180,7 @@ from actual occurrence data after the additive v10 -> v11 migration. Existing rows retain `load_mode=none`, zero rest and NULL targets. Android v12 adds the durable flattened exercise-alias mapping used to resolve retired creator IDs. Desktop schema v12 owns the same alias compatibility boundary. Later additive -desktop migrations reach v18 and Android migrations reach v17 without changing +desktop migrations reach v19 and Android migrations reach v18 without changing that identity contract. The active completed-session exchange is the separate strict `trainlog-mobile-export` V3; V1/V2 remain readable and `TRAINLOG_FORMAT_V1` @@ -237,7 +237,7 @@ Desktop SQLite schema is versioned with: PRAGMA user_version; ``` -The current desktop schema is v18. Schema v9 added an occurrence-owned explicit +The current desktop schema is v19. Schema v9 added an occurrence-owned explicit maximum result; v10/v11 added body-zone and planning metadata; v12 added durable flattened exercise aliases; v13-v18 add machine metadata, feedback and revisions, occurrence tracking snapshots, causal profile state, and AI proposal diff --git a/CHANGELOG.md b/CHANGELOG.md index 64df513..86507f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased — 0.1.2 +- Completed `TRAINLOG_SYNC_DATA_LIFECYCLE_V1` with desktop schema v19 and + Android schema v18. Added explicit staged V4 enriched-history codecs, + causal notes, body-observation session links, stable execution-draft + identities, bounded pending drafts, explicit activation and atomic, + idempotent finalization with stale-replay protection. Active synchronization + remains V3; no service, user database, phone, tag or release artifact was + changed or deployed. + - Completed `TRAINLOG_SYNC_CHARACTERIZATION_V1` without changing production synchronization, schemas, or formats. Added a real Android V3 exporter → desktop importer/exporter → fresh Android importer round trip, and completed diff --git a/README.md b/README.md index 1866bba..7b1ca49 100644 --- a/README.md +++ b/README.md @@ -308,11 +308,12 @@ not contain cloud credentials and does not run `rclone`. As of 2026-09-17: - `TRAINLOG_FORMAT_V1=PASS/FROZEN`; -- desktop SQLite schema v18 and Android SQLite schema v17; +- desktop SQLite schema v19 and Android SQLite schema v18; - Notcurses is the only active desktop terminal backend; - direct storage is `/storage/emulated/0/Documents/Trainlog` under Android's all-files access setting; -- mobile export V3 is active; V1/V2 remain readable legacy inputs; +- mobile export V3 is active; V1/V2 remain readable legacy inputs; explicit V4 + history and execution-draft codecs are staged but not selected by transport; - `STATS_V1=IMPLEMENTED`, `TRAINING_KNOWLEDGE_V1=PASS`, and `SESSION_GENERATOR_V1=PASS` (the generator is hidden pending V2); - `APP_SHELL_V1=IMPLEMENTED_AWAITING_VISUAL_REVIEW_2`; diff --git a/docs/android.md b/docs/android.md index 152c561..70adebc 100644 --- a/docs/android.md +++ b/docs/android.md @@ -90,6 +90,15 @@ so an unchanged companion replay is a skip and cannot resurrect a started or deleted proposal. Neither action manufactures performed sets, completed history, MAX, or feedback. +Android schema v18 additively gives the execution draft its future stable +`session_id`, revision ancestry and `started_at`; adds bounded pending draft, +revision and finalization storage; and adds causal note state plus optional +observation-to-session ownership. Finalization inserts the completed session +with the same stable identities and records its ledger in the transaction that +removes the active draft. Retrying finalization is idempotent, and a stale +draft replay cannot recreate the finalized draft. Raw partial form strings +remain local and are absent from the lifecycle artifact. + The manual synchronization action publishes one prepared Android→PC bundle before it exposes `trainlog-sync-request-v1.json`. The bundle contains mobile V3, mobile equipment definitions, equipment associations V2, exercise aliases diff --git a/docs/architecture.md b/docs/architecture.md index b13bd59..f182d56 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -468,7 +468,9 @@ silently rendered as unclassified. ### Desktop -Desktop SQLite schema v18 is canonical long-term history. Its v15 -> v16 +Desktop SQLite schema v19 is canonical long-term history. Its additive v18 -> +v19 migration stores causal notes and execution-draft lifecycle state without +activating a new transport. Its v15 -> v16 transactional rebuild adds the occurrence-owned `tracking_mode` snapshot; the one-time backfill copies the linked catalogue mode without changing child rows or stable identities. The additive v16 -> v17 migration adds deterministic diff --git a/docs/current_state.md b/docs/current_state.md index 18c3303..65653c3 100644 --- a/docs/current_state.md +++ b/docs/current_state.md @@ -25,9 +25,9 @@ parallel implementation of its rules. | Boundary | Current state | |---|---| | Frozen project exchange | `TRAINLOG_FORMAT_V1=PASS/FROZEN` | -| Desktop SQLite | schema v18 | -| Android SQLite | schema v17 | -| Mobile snapshot | V3 active; V1/V2 readable legacy inputs | +| Desktop SQLite | schema v19 | +| Android SQLite | schema v18 | +| Mobile snapshot | V3 active; V1/V2 readable legacy inputs; explicit V4 codec staged, not selected by transport | | Desktop terminal backend | Notcurses only | | Trainlog product version | `0.1.2` development, synchronized across Android and desktop; latest stable release: `v0.1.1` | | Interface language | `TRAINLOG_I18N_V0_1_1=PASS`: French default; English selectable in Settings → Language on both surfaces | @@ -48,9 +48,10 @@ parallel implementation of its rules. | Web Dashboard visualizations | `WEB_DASHBOARD_VISUALIZATIONS_V1=PASS/FROZEN` | | Web Dashboard V1 | `WEB_DASHBOARD_V1=PASS/FROZEN` | | Local Web | `TRAINLOG_WEB_V1=CONTRACT_FROZEN / IMPLEMENTATION_STARTED` | -| Complete synchronization gap contract | `TRAINLOG_SYNC_GAP_CONTRACT_V1=CONTRACT_FROZEN / IMPLEMENTATION_NOT_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` | | Synchronization characterization | `TRAINLOG_SYNC_CHARACTERIZATION_V1=PASS/FROZEN` | +| Synchronization data/lifecycle slice | `TRAINLOG_SYNC_DATA_LIFECYCLE_V1=PASS/FROZEN` | Desktop and Android schema numbers are independent. Neither changes the frozen Trainlog JSON V1 contract. @@ -72,6 +73,13 @@ their current synchronization state from local typed status and counters; they never inject a raw cross-device French summary into the visible interface. No raw exchange or protocol format changed for interface language support. +Schema v19/v18 now persists enriched history (`ended_at`, causal session, +occurrence and observation notes, and observation-to-session links), stable +execution-draft identities, bounded pending drafts and finalization ledgers. +The explicit `trainlog-mobile-export` V4 and `trainlog-execution-drafts` V1 +codecs are validation-stage entry points only. The active sync engine and +Android inbox/outbox still select V3 and do not move the draft artifact. + ## Storage and synchronization - Android stores capture data in its private SQLite database. diff --git a/docs/database.md b/docs/database.md index bb849e6..b5158ef 100644 --- a/docs/database.md +++ b/docs/database.md @@ -16,8 +16,8 @@ is a later, separately versioned migration. ## 1. Status ```text -TRAINLOG_DATABASE_SCHEMA_VERSION=18 -DATABASE_SCHEMA_V18=IMPLEMENTED +TRAINLOG_DATABASE_SCHEMA_VERSION=19 +DATABASE_SCHEMA_V19=IMPLEMENTED TRAINLOG_FORMAT_V1=FROZEN ``` @@ -36,7 +36,7 @@ PRAGMA user_version; Current value: ```text -18 +19 ``` The independent actual-set loads documented in the current desktop, Android @@ -49,6 +49,12 @@ Supported historical databases are migrated explicitly through the implemented migration chain. A database newer than the running binary understands is rejected. +Version 19 additively stores causal note revisions/current state and staged +execution drafts, their immutable revisions, pending/active state and durable +finalization ledger. It changes no published V1 format and performs no user +database migration until a v19 binary is deliberately deployed and opens that +database. + Version 7 assigns `session_exercises.entry_id` to each stable occurrence. `exercise_id` remains only the catalogue identity and may occur more than once in a session. The v6 → v7 migration rebuilds the obsolete uniqueness diff --git a/docs/design/sync_gap_contract_v1.md b/docs/design/sync_gap_contract_v1.md index 8cb05d6..95f6dac 100644 --- a/docs/design/sync_gap_contract_v1.md +++ b/docs/design/sync_gap_contract_v1.md @@ -400,7 +400,7 @@ de fichiers Android anciens. isolé reproductible ; 2. `TRAINLOG_SYNC_CHARACTERIZATION_V1` : compléter les preuves actuelles sur toutes plateformes ; -3. `TRAINLOG_SYNC_DATA_LIFECYCLE_V1` : mobile V4, drafts et champs perdus ; +3. `TRAINLOG_SYNC_DATA_LIFECYCLE_V1`: mobile V4, drafts and previously lost fields — `PASS/FROZEN`; 4. `TRAINLOG_SYNC_CAUSAL_DELETE_V1` : opérations causales et tombstones ; 5. `TRAINLOG_SYNC_GENERATION_ACK_V1` : manifest, staging, publication, consommation, reprise et ack ; diff --git a/docs/exchange_format.md b/docs/exchange_format.md index a6d7271..4e57e3e 100644 --- a/docs/exchange_format.md +++ b/docs/exchange_format.md @@ -78,6 +78,13 @@ The active completed-session synchronization artifact is separately versioned `trainlog-mobile-export` V3 and is documented in [Synchronization exchange](sync_exchange.md). It does not redefine this frozen V1 schema. +An explicit staged `trainlog-mobile-export` V4 codec carries nullable +`ended_at`, causal note values/revisions and observation `session_id`. A +separate strict `trainlog-execution-drafts` V1 codec carries confirmed business +state, stable draft/session and occurrence identities, ancestry and pending +state; it never carries raw UI form strings. Neither staged codec changes +`TRAINLOG_FORMAT_V1` or is selected by the active synchronization transport. + ## 2. Design goal Trainlog v1 must represent the training patterns required by the initial applications without turning the Android recorder into a complex training platform. diff --git a/docs/roadmap.md b/docs/roadmap.md index f25f454..60da70b 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -19,7 +19,7 @@ distinction between measured values and estimates. ## Current baseline -Desktop schema v18, Android schema v17, Notcurses, direct +Desktop schema v19, Android schema v18, Notcurses, direct `Documents/Trainlog` storage, mobile export V3, Training Knowledge V1, Body Zones V1, Training Feedback V1/V2, STATS V1, and Session Generator V1 are implemented. Session Generator V1 is hidden pending V2. AI session-draft @@ -33,7 +33,7 @@ visualizations are implemented; the other four Web routes remain placeholders. ## Current cursor ```text -CURRENT_OPERATIONAL_CURSOR=TRAINLOG_SYNC_DATA_LIFECYCLE_V1 +CURRENT_OPERATIONAL_CURSOR=TRAINLOG_SYNC_CAUSAL_DELETE_V1 ``` `TRAINLOG_SYNC_GAP_CONTRACT_V1=CONTRACT_FROZEN / IMPLEMENTATION_NOT_STARTED` @@ -123,8 +123,11 @@ it does not authorize silently implementing a page. The frozen contract orders future bounded lots as environment/test, characterization, data/lifecycles, causal deletion, generation/consumption/ack, orchestrator/report, Web API, then button/refresh. The environment/test and -characterization lots are complete; no production synchronization -implementation lot is started. +characterization and data/lifecycle lots are complete. Enriched V4 history and +the separate execution-draft codec are implemented behind explicit entry +points, while active transport remains V3. Causal deletion, +generation/consumption acknowledgement, orchestration/reporting and Web sync +remain unimplemented. `WEB_DASHBOARD_V1=PASS/FROZEN` remains closed and unchanged. ### Gym catalog V1 diff --git a/docs/sync_exchange.md b/docs/sync_exchange.md index 123a301..67193cf 100644 --- a/docs/sync_exchange.md +++ b/docs/sync_exchange.md @@ -2,7 +2,7 @@ ## Machine-exercise Phase 1 compatibility -Desktop schema v18 and Android schema v17 retain mobile export V3, readable V1/V2 imports, +Desktop schema v19 and Android schema v18 retain mobile export V3, readable V1/V2 imports, equipment definitions V1, equipment associations V2, exercise aliases V1, and the BODY ZONES companion without wire-format changes. Machine metadata is not silently added to a frozen artifact: stable exercise IDs and canonical names @@ -44,6 +44,7 @@ SESSION_GENERATOR_V1=PASS BODY_ZONE_SYNC_V1=PASS BODY_ZONE_SYNC_V1_LIVE_DEVICE=PASS TRAINLOG_AI_SESSION_DRAFT_V1=VALIDATION_PENDING +TRAINLOG_SYNC_DATA_LIFECYCLE_V1=PASS/FROZEN TRAINLOG_FORMAT_V1=FROZEN_UNCHANGED ``` @@ -59,6 +60,13 @@ general correction; its older resumed-MAX compatibility remains bounded. Synchronization artifacts are separate from the frozen Trainlog session JSON v1 format. +V4 history and execution-draft V1 are staged codecs with explicit repository +and command-line entry points. They are deliberately absent from +`trainlog_sync_run()`, request/receipt publication and the Android automatic +inbox/outbox. Deployment must stop the old user worker, replace the installed +binary/scripts as one unit, migrate only through the new binary, and restart +only after compatibility checks; this ticket performs none of those steps. + ## 2. Exchange directory Canonical Android shared-storage directory: diff --git a/docs/tests.md b/docs/tests.md index 7abc5ea..0fa713c 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -399,6 +399,15 @@ python3 tools/validate_sync_isolated.py --suite smoke python3 tools/validate_sync_isolated.py --suite full --jdk /usr/lib/jvm/java-17-openjdk ``` +`TRAINLOG_SYNC_DATA_LIFECYCLE_V1` adds schema v19/v18 migration assertions and +Android lifecycle coverage for confirmed-only serialization, persistent +pending state, occupied-singleton refusal, explicit activation, identity- +preserving idempotent finalization and stale replay. The full isolated run at +closure passed 73/73 normal native tests, 73/73 ASan/UBSan native tests and 205 +Android tests (201 passed, four unchanged historical-fixture skips), plus both +Python validators and `assembleDebug`. These are artifact/repository proofs; +they do not claim transport activation or global synchronization atomicity. + Use `--jdk /absolute/jdk17/home` when auto-detection is unsuitable and `--run-parent /absolute/private/parent` to select another parent outside the problematic system `/tmp`. `--keep-run-dir` retains a successful run for