762 lines
43 KiB
Markdown
762 lines
43 KiB
Markdown
# Changelog
|
||
|
||
## Unreleased — 0.1.2
|
||
|
||
- Implemented `TRAINLOG_WEB_SESSIONS_V1` with paged preparation, resume and
|
||
history views, stable details, optimistic/idempotent manual preparation,
|
||
explicit proposal derivation, desktop schema v23, Android schema v22 and the
|
||
separate `trainlog-session-preparations` V1 generation participant.
|
||
|
||
- Added compatible non-destructive generation archival on desktop schema v22
|
||
and Android schema v21. Only exactly acknowledged generations older than the
|
||
two active recovery tips leave admission after a verified durable payload
|
||
copy and audit record; all identities, manifests, ACKs, lineage and causal
|
||
evidence remain stored. Older Android stores can recover exact missing
|
||
producer-side ACK rows from the desktop consumer's durable ledger, with
|
||
strict run, peer, generation and manifest revalidation. A correlated Android
|
||
capacity error now reaches the Web without waiting for a transport timeout,
|
||
and the prepared-items tile can inspect every proposal rather than only its
|
||
first compact summary.
|
||
|
||
- Completed the controlled schema-v22/schema-v21 rollout without uninstalling
|
||
or clearing Android data. The production Android archive uses a supported
|
||
post-rename file durability barrier on emulated external storage, and the
|
||
desktop publishes each complete MTP generation before its correlated
|
||
reference. Two real post-migration bidirectional exchanges, separated by a
|
||
Trainlog-service restart, completed with durable ACKs and no session
|
||
duplication. The expected AI proposal retained its identity, six entries,
|
||
and `pending` state on Android and remained independently visible in Web.
|
||
|
||
- Fixed a production full-generation timeout caused by recursively uploading
|
||
retained staging and unrelated transport history on every MTP push. Each
|
||
phase now publishes a private bounded outbox containing only its request,
|
||
ACK, and current referenced generation, while preserving every retained
|
||
generation, tombstone, and causal proof. Transport expiry has a stable
|
||
browser-facing code and action instead of a truncated traceback.
|
||
The reciprocal pull now reads only current coordination objects and the
|
||
exactly referenced Android generation instead of recursively mirroring
|
||
retained Android and desktop history.
|
||
|
||
- Replaced the Web Next Session placeholder with a separate read-only Core
|
||
projection that distinguishes AI proposals from active/pending execution
|
||
drafts without redefining the frozen Dashboard field or counting targets as
|
||
performed work. The browser preserves the last successful durable view
|
||
across refresh failures and uses one abortable, per-run ordered sync poller.
|
||
|
||
- 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.
|
||
|
||
- Added a bounded Android package-version override and made the schema-v17
|
||
backup bridge produce a signed release APK, allowing a strictly increasing
|
||
private update chain without changing Trainlog schemas or protocols.
|
||
|
||
- Generalized bridge restore/migration validation to preserve every historical
|
||
SQLite value whether a real backup contains an active draft or legitimately
|
||
contains none.
|
||
|
||
- Made relocatable launchers resolve stable user-bin symlinks to their physical
|
||
versioned bundle before loading matching binaries and helpers.
|
||
|
||
- Made the Web sync button generate cryptographic UUIDv4 request IDs on the
|
||
loopback HTTP hostname where `crypto.randomUUID()` is unavailable.
|
||
|
||
- Included the exercise-name and training-knowledge modules required by the
|
||
packaged generation worker, with an isolated runtime-import regression.
|
||
|
||
- Closed the native candidate warning gate with checked path and HTTP response
|
||
bounds, strict GCC and Clang builds, full Clang ASan/UBSan validation, and a
|
||
stable concurrent object-I/O MTP double. Rebuilt the desktop, current Android
|
||
and non-installed schema-v17 bridge candidates with recorded digests; no
|
||
service, device, user database, signing secret or deployment was touched.
|
||
|
||
- Normalized the recent synchronization, generation-MTP, Android backup,
|
||
Web Dashboard serialization, tests, I/O doubles and packaging code for human
|
||
readability. Added scoped C formatting rules and review guidance without
|
||
changing synchronization protocols, assertions, deployment state or runtime
|
||
behavior.
|
||
|
||
- Added the production libudev/libmtp generation adapter with bounded peer
|
||
selection, object transfer and manifest-last publication; wired the trusted
|
||
orchestrator mode and proved the full Firefox/Android/desktop conversation
|
||
with an I/O-boundary object double. Added complete versioned Android
|
||
backup/verify/restore and a reproducible, non-installed schema-v17 bridge
|
||
candidate with v17 round-trip and v17-to-v20 migration tests. Physical MTP,
|
||
signing, device installation, user-data operations and rollout remain
|
||
pending.
|
||
|
||
- Added opt-in foreground generation coordination, peer-evidenced capabilities,
|
||
truthful bounded Web progress, descendant cleanup, an integrated Android ↔
|
||
desktop Firefox proof, and synthetic candidate/SQLite recovery tooling on the
|
||
development branch. Physical MTP and deployment remain pending.
|
||
|
||
- Completed the grouped `TRAINLOG_SYNC_WEB_END_TO_END_V1` mission: the opt-in
|
||
full-generation orchestrator, protected asynchronous Web API, global sync
|
||
control, durable reconnect reporting, Dashboard refresh and read-only draft
|
||
summary pass isolated C, Python, Android, frontend and Firefox validation.
|
||
Default V3, physical MTP, Drive and deployment remain unchanged.
|
||
|
||
- Completed `TRAINLOG_SYNC_GENERATION_ACK_V1` with desktop schema v21 and
|
||
Android schema v20. Added coherent per-platform capture, strict bounded
|
||
manifest V1, immutable manifest-last publication, whole-generation SQLite
|
||
consumption, pair-scoped lineage, durable consumed/rejected ACK V1 replay,
|
||
and a separate causal-operation publication ledger. Real isolated Android →
|
||
desktop and desktop → Android chains use production entry points and retain
|
||
operation identity across generations. Automatic V3/MTP selection and all
|
||
operational services remain unchanged.
|
||
|
||
- Completed the residual causal-deletion evidence with real Android and
|
||
desktop producers for exercise, body-observation, custom-equipment, feedback
|
||
and BODY ZONE relation targets, including production replica exchange,
|
||
retained-history/current-reader checks, reopen/replay and stale-companion
|
||
refusal.
|
||
|
||
- Closed the causal-deletion correctness review: deletion predecessors now
|
||
cover affected session children, measurements, links, notes and immutable
|
||
feedback revisions; supported corrections preserve an intervening mutation
|
||
marker even after a content revert. Imported operations share built-in
|
||
authorization with local deletion, execution drafts use their stable
|
||
cross-platform revision identity, protected legacy companions refuse unsafe
|
||
replay, and causal artifact reads/exports enforce count and byte bounds
|
||
before destructive effects.
|
||
|
||
- Completed `TRAINLOG_SYNC_CAUSAL_DELETE_V1` with desktop schema v20 and
|
||
Android schema v19. Added a strict bounded staged causal-deletion artifact,
|
||
durable operation/state records, domain-specific deletion effects, causal
|
||
conflict and replay handling, and legacy snapshot non-resurrection gates.
|
||
Android and desktop both produce and consume the artifact in isolated tests;
|
||
automatic transport, generation acknowledgement and deployment remain
|
||
inactive.
|
||
|
||
- 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.
|
||
|
||
- Closed the lifecycle validation evidence with real Android/desktop V4
|
||
history and execution-draft round trips in both producer directions. Fixed
|
||
Android V4 import so validated target, load, and rest fields are persisted,
|
||
reconciled the 73/75 native count to the two `web=auto` frontend tests, and
|
||
documented identical pre-existing GCC 16 `-Wmisleading-indentation`
|
||
failures on baseline and branch while retaining Clang 22 strict green
|
||
builds. V4 remains staged and inactive.
|
||
|
||
- 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
|
||
current-behavior evidence for stable identities, occurrence/set ordering,
|
||
exact replay versus correction, local-only field handling, inter-artifact and
|
||
delete-before-send partial failure, request/receipt replay and marking, and
|
||
contention on the real private-XDG synchronization lock. V4, draft transport,
|
||
general tombstones, coherent generations, causal merge, and durable peer
|
||
consumption acknowledgement remain future work.
|
||
|
||
- Reconciled canonical documentation with the implemented 0.1.2 development
|
||
state, kept v0.1.1 and future synchronization scope explicit, established
|
||
English as the repository documentation/release-note language, and added a
|
||
reusable tag-scoped English source for the v0.1.1 public notes. No production
|
||
behavior, schema, format, service, tag, or release asset changed.
|
||
|
||
- Completed `TRAINLOG_SYNC_TEST_ENV_V1` without changing production behavior,
|
||
schemas or formats. `tools/validate_sync_isolated.py` now validates JDK 17 and
|
||
the effective Gradle JVMs, creates unique private HOME/XDG/native/JVM tmp,
|
||
exchange, database and report paths, runs bounded preflight/smoke/full suites,
|
||
counts Android XML results, propagates failures and interruptions, and cleans
|
||
only its owned successful run. Unit and Robolectric coverage proves bounded
|
||
cleanup, distinct runs, process termination, no default real transport and
|
||
effective `java.io.tmpdir` propagation.
|
||
|
||
- Froze `TRAINLOG_SYNC_GAP_CONTRACT_V1` without changing production sync,
|
||
schemas or published formats. The contract distinguishes current evidence
|
||
from future behavior and defines domain ownership, active-draft lifecycle,
|
||
lost fields, causal deletion, conflicts, coherent generations, verified
|
||
consumption/acknowledgement, compatibility, reporting, a future Web service
|
||
boundary and dependency-ordered implementation lots. Added isolated
|
||
production-path characterization of V3 field loss, snapshot resurrection and
|
||
per-artifact rollback; existing Android coverage remains the proof of draft
|
||
exclusion followed by finalized-session export.
|
||
|
||
- Development opened after the stable `v0.1.1` release. The complete Web
|
||
Dashboard is now `WEB_DASHBOARD_V1=PASS/FROZEN`; Analyse, Programmes,
|
||
Sessions, and Exercises remain placeholders. The current operational cursor
|
||
is `TRAINLOG_SYNC_CHARACTERIZATION_V1`; its future protocol work has not
|
||
started.
|
||
|
||
## 0.1.1 — 2026-09-16
|
||
|
||
- Completed `TRAINLOG_ANDROID_FIELD_INPUT_REFINEMENT_V1`: active and completed
|
||
occurrence handles now keep one stable `entry_id`-keyed pointer gesture alive,
|
||
accumulate total drag distance, jump directly across multiple positions, show
|
||
residual pointer-following motion, restore the origin on cancellation, and
|
||
commit only once at completion where persistence applies. Decimal distance,
|
||
speed, MAX, target-load, and set-load editors use decimal keyboards, accept
|
||
both `.` and `,`, preserve incomplete typing states, and parse finite
|
||
locale-independent values only at commit. Units, schemas, formats, identities,
|
||
active/completed ownership, and version 0.1.1 remain unchanged.
|
||
|
||
- Completed `TRAINLOG_ANDROID_COMPLETED_SESSION_REORDER_V1`: the Android
|
||
completed-session correction form reuses the dedicated localized right-side
|
||
drag handle and accessibility move actions. Reordering remains transient until
|
||
Save; Cancel/Back writes nothing, while Save atomically replaces positions and
|
||
any factual corrections under the same session/entry/exercise identities.
|
||
Stable Compose keys keep editor state attached to `entry_id`; equipment,
|
||
targets, actuals, MAX, feedback revisions, and J+1 ownership survive. Existing
|
||
V3 synchronization reconciles the same desktop session without duplication.
|
||
No schema, exchange format, active-session behavior, or version changed.
|
||
|
||
- Completed `TRAINLOG_ANDROID_FIELD_WORKFLOW_REFINEMENT_V1`: Android now uses a
|
||
full-width semantic-success **Add to session** action, provides a dedicated
|
||
accessible right-side drag handle for durable active-draft reordering, and
|
||
supports atomic completed-session factual correction. Reorder and correction
|
||
retain stable session, occurrence, exercise, equipment, plan, actual, feedback,
|
||
and follow-up ownership; corrected facts continue through the existing V3
|
||
synchronization identity. Continuous values reject non-finite input and show
|
||
explicit km, km/h, and seconds units. No SQLite schema, exchange format,
|
||
desktop/TUI behavior, or product version changed.
|
||
|
||
- Documented stable-release distribution through GitHub and Forgejo Releases,
|
||
including
|
||
prebuilt Android and architecture-specific dynamically linked Linux assets,
|
||
SHA-256 verification, runtime/build/optional dependencies, and the release
|
||
signing and exact-tag requirements. The Android artifact is built with the
|
||
durable Trainlog release identity and is verified before publication.
|
||
|
||
- Completed `TRAINLOG_I18N_V0_1_1`: Trainlog 0.1.1 is one synchronized Android
|
||
and desktop product version, with French as the default interface language
|
||
and English selectable through **Settings → Language** on both surfaces.
|
||
The preference is local presentation state (dedicated Android
|
||
SharedPreferences; desktop XDG `trainlog/presentation.conf`) and successful
|
||
selection updates the interface immediately. Localized Trainlog-owned text,
|
||
BODY ZONE labels selected by stable IDs, and visible number/date formatting
|
||
do not change training data, user exercise/catalogue names, IDs, SQLite,
|
||
schemas, exchange/protocol artifacts, AI, MAX, or feedback. Desktop and
|
||
Android synchronization views render local typed status/counters; raw
|
||
core/receipt/history summaries remain opaque protocol/operational bytes and
|
||
are never injected as cross-device French text. Final validation passed
|
||
60/60 normal and 60/60 ASan/UBSan desktop tests, Android 202 total tests
|
||
(198 passed, 4 skipped, 0 failed), both validators, source-derived
|
||
`TRANSLATABLE_UI=0`, and Android resource parity. Real device/manual visual
|
||
switching remains an explicit smoke validation.
|
||
|
||
- Completed `TRAINLOG_FULL_REPOSITORY_DOCUMENTATION_AUDIT_V2`: added the
|
||
canonical documentation index, made README a concise entry point, separated
|
||
current state from future roadmap ownership, corrected current schema and
|
||
validation descriptions, and added concise English ownership headers across
|
||
previously undocumented C, Kotlin, Python, and shell sources. The audit
|
||
changes documentation comments only and introduces no functional behavior.
|
||
|
||
- Fixed fresh Android database body-zone reconstruction by applying the
|
||
PC-published body-zone companion immediately after catalog, flattened aliases
|
||
and strict profile-state, before fallible downstream session, equipment, AI
|
||
draft and feedback imports. Regression coverage rebuilds several mappings in
|
||
one inbox pass, resolves a retired exercise ID only through its durable alias,
|
||
preserves the one-sync AI draft, and proves idempotent replay without identity
|
||
mutation or duplicate zone rows.
|
||
|
||
- Redesigned the Android Home, Sessions, Exercise Catalogue, active-session
|
||
and completed-session-detail action layouts with balanced icon tiles,
|
||
bounded internal catalogue scrolling, and prominent accessible buttons,
|
||
plus uniform full-width icon-only destructive actions with contextual
|
||
TalkBack labels, without changing confirmation, navigation callbacks, or
|
||
domain/storage/sync behavior.
|
||
|
||
- Added an Android confirmation dialog before deleting an imported AI session
|
||
draft. Cancel, Back and outside dismissal are non-mutating; only the
|
||
destructive confirmation invokes the existing deleted-tombstone operation.
|
||
|
||
- Replaced Android SAF folder grants with user-enabled
|
||
`MANAGE_EXTERNAL_STORAGE` access to the single fixed path
|
||
`/storage/emulated/0/Documents/Trainlog`. Android opens the system all-files
|
||
permission screen, writes canonical artifacts through fsync plus
|
||
same-directory replacement, reads PC artifacts directly, and removes stale
|
||
tree-URI preferences. Desktop publication remains `Documents/Trainlog`; the
|
||
historical Download tree and recovery backup remain untouched.
|
||
|
||
- Added `TRAINLOG_AI_SESSION_DRAFT_V1` as a separate strict proposal path:
|
||
desktop schema v18 imports one Drive source with `aid_` identity/digest
|
||
idempotence and post-commit archive bookkeeping, then publishes the bounded
|
||
`trainlog-ai-session-drafts` V1 Android companion in durable deterministic
|
||
batches, marking only successful MTP publications. Entry notes are rejected;
|
||
only draft-level notes belong to the source contract. Inbound helper outcomes
|
||
remain visible without turning Drive/archive/fetched-invalid results into a
|
||
failed device sync. Android schema v17 keeps
|
||
those proposals separate from its singleton active capture draft and retains
|
||
start/delete tombstones against replay. Automated contract coverage exists;
|
||
the required real Drive and Android-triggered bidirectional smoke validation
|
||
remains pending.
|
||
|
||
- Fixed automatic Android→PC exercise-alias imports when the desktop binary is
|
||
installed outside the repository build tree. Python sync helpers now resolve
|
||
from Meson's authoritative tools directory, stale result files are truncated
|
||
before resolution, and bounded child stderr/exit diagnostics reach sync
|
||
history instead of collapsing to a generic import failure.
|
||
- Added `TRAINLOG_AI_EXPORT_V1`, a deterministic local JSON history export for
|
||
manual external analysis. It opens desktop SQLite explicitly read-only,
|
||
preserves occurrence-owned immediate feedback and session-owned follow-ups,
|
||
and emits no inferred recommendations or progression.
|
||
- Added the shared desktop post-sync publication: successful TUI and
|
||
Android-requested sync runs regenerate the AI export and invoke external
|
||
`rclone copyto` for Google Drive. Export/Drive failures remain visible but do
|
||
not invalidate an already successful Trainlog synchronization.
|
||
|
||
- Fixed Android-triggered synchronization so the complete current Android→PC
|
||
companion bundle is published before the request signal, including Training
|
||
Feedback V2 and Exercise Profile State V1. Desktop orchestration now refuses
|
||
stale temporary profile-state reuse and reports a specific missing causal
|
||
companion when a modern same-ID profile mismatch requires it.
|
||
- Made Android exchange-file reuse exact and directory-scoped: pending,
|
||
trashed, unrelated, and conflict-numbered MediaStore rows no longer enter
|
||
canonical selection, while genuine duplicate exact names fail closed.
|
||
- Hardened the shared Android SAF publisher so every outbound companion and
|
||
sync request rewrites an existing exact canonical document with truncation,
|
||
never selects historical `(N)` copies, and reports
|
||
`SAF_CANONICAL_NAME_CONFLICT` before writing when a provider renames a newly
|
||
created document.
|
||
- Added an exact-document fallback for Samsung Android 16
|
||
`ExternalStorageProvider`, whose child query can omit ownerless MTP files even
|
||
though creation detects their names. Canonical rows are reconstructed only
|
||
beneath the granted tree and verified by exact provider display name;
|
||
historical suffixes remain untouched.
|
||
|
||
## Unreleased — Desktop historical tracking snapshot
|
||
|
||
- Added desktop schema v17 / Android schema v16 causal current-profile state,
|
||
bounded 32-revision transitive ancestry, deterministic bidirectional
|
||
convergence, and explicit concurrent-edit conflicts; legacy feedback without
|
||
`ended_at` now shows approximate H+ from
|
||
valid `started_at` instead of a misleading during-session label.
|
||
- Added desktop schema v16 with an atomic v15 backfill of occurrence-owned
|
||
`session_exercises.tracking_mode`, preserving identities and all child facts.
|
||
- Switched historical readers and V3 exchange to the occurrence snapshot while
|
||
retaining catalogue profile modes as future-entry defaults.
|
||
- Enabled explicitly confirmed future-only tracking/profile edits in the TUI
|
||
without rewriting completed sessions.
|
||
|
||
## Unreleased — Training feedback UX and safety
|
||
|
||
- Added additive schema v15 immutable feedback revisions and Training Feedback
|
||
V2 with V1 import compatibility.
|
||
- Made saved exercise feedback and session follow-ups correctable on Android
|
||
while preserving root identity, observation time, H+ placement and history.
|
||
- Preserved occurrence `entry_id` and feedback through draft edit,
|
||
reconstruction, finalization and completed-session correction.
|
||
- Added explicit destructive confirmation to the reachable Android and TUI
|
||
session removal/abandon paths.
|
||
|
||
## Unreleased — MACHINE_EXERCISE_MODEL_V1
|
||
|
||
- Add desktop and Android schema v13 for machine-specific exercise metadata.
|
||
- Preserve stable IDs for pure renames and introduce the five approved UUIDv4
|
||
identities for Plate Loaded Leg Press, Treadmill, Pec Fly, Chin Assist, and
|
||
Dip Assist.
|
||
- Make exact manifest splits transactional and idempotent while preserving all
|
||
occurrence child facts and unresolved provenance.
|
||
- Remove Equipment from normal Android and TUI navigation while retaining its
|
||
Phase 1 storage and sync compatibility roles.
|
||
|
||
- Added `PERCENT_MAX_INPUT_V1` as a transient user calculator in TUI planning
|
||
and both generator previews: exact exercise/equipment external-load context,
|
||
integer 1..100, `MAX × percentage / 100`, no recommendation, and only the
|
||
resulting target kg persisted. Automatic generator policy V1 is unchanged.
|
||
- Repaired TUI `/` through the stable action registry, deduplicated actions by
|
||
stable ID, strengthened Lavender plus textual selection states, compacted
|
||
Android generator choices into localized chips, and made generator duration,
|
||
shortfall, warm-up and cool-down limitations explicit.
|
||
|
||
All notable changes to Trainlog are documented here.
|
||
|
||
Detailed implementation chronology remains available in Git history and
|
||
`docs/reviews`. This file summarizes the current unreleased product baseline.
|
||
|
||
## Unreleased
|
||
|
||
### Added
|
||
|
||
- `TRAINLOG_TUI_STATISTICS_CALENDAR_BUCKETS_V1=PASS`: Training `7j` now means
|
||
the current Monday–Sunday calendar week and compares calendar weeks; `30j`
|
||
means the current Gregorian month and compares calendar months. Membership
|
||
follows the civil date persisted in each timestamp, empty intermediate
|
||
periods remain zero bars, localized labels expose the calendar boundaries,
|
||
and exact month endpoints cover ordinary and leap-year February.
|
||
|
||
- `TRAINLOG_TUI_STATISTICS_PERIOD_BUCKET_SIZE_FIX=PASS`: the selected Training
|
||
period now controls both summary depth and comparison-bucket size. `7j` uses
|
||
exact consecutive 7-day buckets, `30j` uses exact consecutive 30-day buckets
|
||
anchored on the current local date, and `Tout` selects one stable weekly or
|
||
calendar-month scale from total historical duration. Empty intervals remain
|
||
explicit zero bars and boundary observations are counted once.
|
||
|
||
- `TRAINLOG_TUI_STATISTICS_PERIOD_BUCKETING_V1=PASS`: Training summaries keep
|
||
their rolling 7-day/30-day facts while charts compare consecutive exact
|
||
Monday–Sunday buckets. The 7-day view shows up to four available weeks, the
|
||
30-day view shows all intersecting weeks, empty periods remain zero bars, and
|
||
complete history adapts from weekly to monthly totals beyond 128 active
|
||
weeks without sampling away totals.
|
||
|
||
- `TRAINLOG_TUI_STATISTICS_REFINEMENT_V1=PASS`: finite statistics windows now
|
||
retain their complete time domain; weekly totals use local Monday buckets,
|
||
explicit empty weeks, zero baselines and discrete Notcurses bars. Wide
|
||
training summaries are grouped into semantic panels, zone bars expose raw
|
||
counts on one shared scale, exercise lists show factual summaries, and MAX
|
||
defaults to exercises with an explicit recorded result while preserving an
|
||
opt-in all-compatible view and prefix search.
|
||
|
||
- `TRAINLOG_TUI_STATISTICS_V1=PASS`: Statistiques is now the desktop analysis
|
||
center for body history, factual global training activity, canonical
|
||
exercise histories, persisted primary/secondary body-zone activity and
|
||
explicit MAX history. Read-only C17 aggregations feed responsive Notcurses
|
||
views and the shared Braille chart; valid loaded volume, planned/actual and
|
||
feedback ownership rules deliberately exclude unsupported inference. No
|
||
Android, database-schema, synchronization or exchange-format behavior changed.
|
||
|
||
- `TRAINLOG_TUI_MEASUREMENTS_GRAPH_V1=PASS`: Statistiques / Mensurations now
|
||
uses a reusable Notcurses chart with true elapsed-time spacing, labelled
|
||
padded value scales, a 2x4 Unicode Braille line raster, distinct accent
|
||
markers for stored observations, responsive sparse-profile layout, and
|
||
terminal-free geometry/raster regressions. No database, measurement, Android,
|
||
or synchronization semantics changed.
|
||
|
||
- `APP_SHELL_V1=IMPLEMENTED_AWAITING_VISUAL_REVIEW_2`: a shared seven-root
|
||
application shell—Accueil, Séances, Exercices, Équipements, Statistiques,
|
||
Synchronisation and Paramètres—on the Notcurses TUI and Android Material 3
|
||
drawer. Séances now contains the existing generator, current/manual session
|
||
entry and completed history; existing body and MAX views are reached from
|
||
Statistiques. The TUI adds its run-scoped multi-plane shell, one event loop,
|
||
stable-ID list/focus restoration, bounded UTF-8 search/forms, F6 Navigation,
|
||
F7 shared actions, compact/sidebar thresholds, and explicit transient leave
|
||
guards. Android adds typed controller-owned routes, local vectors, 48 dp
|
||
actions and guarded navigation. The change adds no statistics, schema,
|
||
synchronization artifact or exercise-domain semantics. Automated validation
|
||
passed. A second automated repair review covered root search/action dispatch,
|
||
F6/F7 focus/selection restoration, shell hubs/catalogues and Android compact
|
||
presentation/latest-MAX semantics; human visual/accessibility review remains
|
||
pending.
|
||
|
||
- `SESSION_GENERATOR_V1=PASS`: one frozen shared policy; deterministic bounded previews for
|
||
11 BODY ZONES and four goals; explicit incomplete coverage and recorded-dose
|
||
recency; observed exact-equipment 28-day load anchors without MAX-derived
|
||
numeric fallback; Android normal-draft and TUI normal-editor acceptance; an
|
||
additive Android v10 -> v11 plan migration; and separate strict V3 mobile
|
||
exchange preserving plans with actual occurrence data. V1/V2 remain readable.
|
||
|
||
- `TRAINING_KNOWLEDGE_V1` read-only scientific knowledge infrastructure:
|
||
six authored, versioned JSON catalogs with cited references; deterministic C
|
||
generation; Android immutable asset loading; stable-ID catalog queries; and
|
||
desktop/Android composition of persisted exercise zones, compatible
|
||
equipment, explicit MAX and bounded occurrence/set history. The feature
|
||
introduces no schema migration, database seeding, synchronization artifact,
|
||
runtime prescription or generated UUID association. Scientific review,
|
||
independent temporal review, final engineering review, repair verification,
|
||
and final executable validation passed. The initial audit's four findings
|
||
were closed by one bounded repair chain. See
|
||
`docs/reviews/training_knowledge_v1_temporal_contract.md` and
|
||
`docs/domain/knowledge_system.md`.
|
||
|
||
- `BODY_ZONES_V1`: the canonical `catalog/body-zones-v1.json` taxonomy with
|
||
stable IDs, French display metadata, hierarchy, deterministic sort order and
|
||
exact stable-exercise-ID migration evidence;
|
||
- one primary plus multiple distinct secondary body-zone relations on desktop
|
||
and Android, with explicit unclassified history, transactional creation/edit,
|
||
exercise detail summaries, parent/descendant filters, prefix-search
|
||
composition, and custom-exercise support;
|
||
- one strict bidirectional `trainlog-exercise-body-zones` v1 companion carrying
|
||
`exercise_id`, nullable primary ID and ordered secondary IDs; replay is
|
||
idempotent, one-sided edits reconcile, simultaneous divergence conflicts,
|
||
secondary lists are never unioned automatically, and the publishing peer
|
||
records the exact published snapshot as its common baseline;
|
||
- generator-ready read composition for descendant and primary-only exercise
|
||
selection, direct zone relations, existing performance history and explicit
|
||
MAX history without duplicating historical or MAX data;
|
||
- taxonomy, schema migration, relation constraint, filtering, identity-merge,
|
||
reopen, companion replay/update/conflict and Android repository regressions;
|
||
|
||
- explicit MAX result mode for `max_test` sessions: exercise, optional
|
||
equipment context and positive `max_weight_kg`, with no synthetic set or
|
||
repetition;
|
||
- Android and TUI max-only entry/edit/detail flows, Android latest max per
|
||
exercise, and stable-ID continuation of a completed Test max;
|
||
- V2 round-trip of explicit max results in both directions, including bounded
|
||
reconciliation of an appended or corrected continuation of the same
|
||
max-test session;
|
||
- desktop and Android schema v9 migrations that convert only an unambiguous
|
||
sole `1 rep × positive load` legacy result and preserve ambiguous attempts;
|
||
- explicit-max persistence, migration, sync and same-machine/different-movement
|
||
regression coverage;
|
||
|
||
- desktop equipment v8: a supplied catalogue generated from
|
||
`catalog/equipment-v1.json`, browse/search/detail views, and local custom
|
||
equipment creation/selection; occurrence links resolve supplied or local
|
||
definitions and show unknown historic references explicitly;
|
||
|
||
- multi-occurrence session V2: stable per-occurrence `entry_id`, repeated
|
||
catalogue exercises in one session, per-set actual weights, and occurrence
|
||
equipment associations across Android, desktop, import and export;
|
||
- structured Android and Notcurses per-set row editing: independent actual
|
||
repetitions and nullable Charge/Assistance values, ordered add/delete/edit
|
||
operations, and ordered history/detail presentation without target-value
|
||
substitution;
|
||
- shared versioned equipment catalogue, Android machine selection/search,
|
||
Android-local custom equipment creation, and explicit rejection of unknown
|
||
equipment identities rather than silent association loss;
|
||
|
||
- `trainlog-equipment-definitions` v1, with directional Android-to-PC and
|
||
PC-to-Android filenames, strict stable definition fields, additive
|
||
reconciliation, reserved supplied-manifest IDs, and explicit divergence
|
||
conflicts;
|
||
- explicit TUI/shared-engine synchronization actions: `a` Android -> PC, `p`
|
||
PC -> Android, and `b` inbound then outbound bidirectional synchronization;
|
||
each opens one direction-specific confirmation, `Enter` runs it once, `Esc`
|
||
cancels without an operation, `r` only refreshes device status, and the
|
||
former `s` shortcut is inert;
|
||
- bounded V2 exercise reconciliation for distinct IDs with equal normalized
|
||
names: modes and represented invariants must match, field masks must be
|
||
comparable, desktop identity stays canonical, and the richer bit-mask union
|
||
is retained without changing historical occurrence snapshots;
|
||
- regression coverage for identical/different-ID profiles, compatible
|
||
subset/superset masks, incompatible collisions, the real Marche identity
|
||
pair, full Android -> PC import and stable PC ↔ Android replay;
|
||
|
||
- Android `EXERCISE_EDIT_V1`: visible catalog editing, stable-ID name rename,
|
||
explicit invalid/conflict/profile/database results, and profile locking once
|
||
completed history or an active draft references the exercise;
|
||
- `ANDROID_BANNER_PARITY_V1`: the earlier Android `◆ TRAINLOG ◆` header
|
||
component matched the compact Notcurses banner's accent and muted context
|
||
rhythm. APP_SHELL_V1 supersedes that per-page presentation with the fixed
|
||
Material 3 `AndroidAppShell` top bar;
|
||
|
||
- one durable Android active-session draft with Home resume, raw form restore,
|
||
confirmed discard and draft-only exercise removal;
|
||
|
||
- native Kotlin/Compose Android capture client;
|
||
- Android local exercise, session, continuous-activity, and body persistence;
|
||
- C17/Notcurses desktop TUI with direct session entry and durable SQLite history;
|
||
- profile-aware exercise model using recording mode, tracking mode, and
|
||
supplemental fields;
|
||
- continuous activity persistence without synthetic sets;
|
||
- explicit table-based desktop actual-set entry, with independently added rows
|
||
and no compact performed-repetition input;
|
||
- persisted desktop session editing and exercise removal;
|
||
- Android current-session draft exercise removal;
|
||
- body-observation history, editing, graphs, and normalized overlays;
|
||
- exercise performance history;
|
||
- direct physical Android USB/MTP discovery with libudev/libmtp;
|
||
- direct MTP read/write/list/delete support without filesystem mounts;
|
||
- Android full mobile snapshot export;
|
||
- strict idempotent desktop mobile importer;
|
||
- PC canonical exercise-catalog publication to Android;
|
||
- automatic Android snapshot maintenance;
|
||
- Android `Synchroniser maintenant` request flow;
|
||
- shared C bidirectional synchronization engine;
|
||
- `trainlog-syncd` user-session synchronization agent;
|
||
- request/receipt synchronization protocol;
|
||
- stable `sy_<uuid-v4>` synchronization identities;
|
||
- structured synchronization history with selectable TUI list/detail views.
|
||
|
||
### Changed
|
||
|
||
- desktop schema v11 additively introduces `exercise_body_zones` and its
|
||
internal sync-baseline table; Android schema v10 introduces the equivalent
|
||
relations. Both migrations seed only manifest mappings proven by stable
|
||
`exercise_id`, leave uncertain exercises unclassified, and preserve all
|
||
session, occurrence, set, MAX, equipment and body-observation identities;
|
||
- Android and TUI exercise catalog workflows now select translated manifest
|
||
values, derive group labels, exclude a primary from secondary selection and
|
||
combine hierarchy-aware zone filtering with normalized prefix search;
|
||
|
||
- desktop schema v10 losslessly rebuilds only `performed_sets` to accept an
|
||
explicit zero actual `weight_kg`; historic NULL and positive actual loads
|
||
remain unchanged, while planned targets and explicit MAX results stay
|
||
strictly positive;
|
||
- desktop and Android schema v9 add one-to-one completed/draft max-result rows;
|
||
`TRAINLOG_FORMAT_V1` remains frozen and V1 export refuses explicit MAX data
|
||
rather than losing or fabricating it;
|
||
- desktop and Android schema v8 preserve existing equipment references while
|
||
permitting custom definitions with `load_semantics = none`; Android's v7 ->
|
||
v8 migration is non-destructive;
|
||
- custom definitions reconcile before V2 mobile/association artifacts in each
|
||
direction. The V2 mobile and association shapes are unchanged;
|
||
|
||
- desktop SQLite schema v7 and Android SQLite schema v7 preserve historic rows
|
||
while adding durable occurrence identities and occurrence-level equipment;
|
||
- the then-active Android↔PC completed-session exchange was V2; frozen V1
|
||
artifacts remain readable as historical formats and are not redefined for
|
||
repeated occurrences; the current active artifact is separately versioned V3;
|
||
- synchronization invokes each local helper with the explicit XDG-resolved
|
||
desktop database path and records the concrete equipment-import failure;
|
||
|
||
- same-ID Android ↔ PC catalog reconciliation updates display-name metadata in
|
||
place. Compatible different-ID normalized-name collisions now merge through
|
||
the explicit V2 policy; incompatible collisions still reject atomically;
|
||
|
||
- Android local SQLite v3 -> v4 additive migration for structured active drafts;
|
||
- completed-session insertion and draft clearing are atomic; drafts remain
|
||
excluded from completed history and frozen mobile export;
|
||
|
||
- desktop SQLite schema evolved to v5;
|
||
- schema v5 permits targetless set-session rows for actual-only mobile data;
|
||
- heterogeneous performed sets are preserved without inventing a uniform target;
|
||
- Android/desktop synchronization uses dedicated versioned artifacts instead of
|
||
modifying frozen Trainlog JSON v1;
|
||
- PC and TUI synchronization paths now share one engine;
|
||
- Android PC-created artifact access uses a persistent SAF grant for
|
||
`Download/Trainlog`;
|
||
- the Android data package is no longer accidentally hidden by a broad
|
||
repository `data/` ignore rule;
|
||
- user-facing session history timestamps use `DD/MM/YYYY HH:MM` while canonical
|
||
storage remains RFC3339.
|
||
|
||
### Fixed
|
||
|
||
- a newly published custom-exercise zone state now establishes the publisher's
|
||
comparison baseline as well as the receiver's; a later peer-only edit no
|
||
longer produces a false simultaneous-conflict result;
|
||
- secondary-only body-zone states are rejected consistently by C, Kotlin and
|
||
Python boundaries instead of being persisted but hidden by exercise detail;
|
||
- touched migration/custom-equipment/body-metric/TUI C regressions now return
|
||
a failing process status from `main()`; the repaired workflow fixture uses a
|
||
real in-memory database instead of passing an invalid null handle;
|
||
- synchronization summaries no longer add exercise reconciliations to the
|
||
`exercices ajoutés` value. A compatible different-ID lookup that makes no
|
||
persistent change is reported as an idempotent skip, while real insertions
|
||
and real reconciliation mutations retain distinct counters. A production
|
||
PC-exporter/Android-importer regression proves zero additions and exact
|
||
business-table stability on the second and third imports;
|
||
- equipment companion import previously omitted its required `--database`
|
||
argument and blocked synchronization after a successful session import;
|
||
- PC catalogue/mobile export paths now accept schema v7 and preserve catalogue
|
||
tracking metadata; Android completed-session equipment editing now targets
|
||
the stable occurrence `entry_id`, not an ambiguous catalogue exercise ID;
|
||
- Android scoped-storage suffix selection now covers equipment associations as
|
||
well as mobile/definition artifacts; a historic V1 snapshot cannot consume a
|
||
neighboring V2 equipment companion;
|
||
- desktop-generated session occurrences now receive `sxe_<uuid-v4>` rather
|
||
than the synchronization-run `sy_` prefix; public generator capacity and C17
|
||
regression coverage include the three-character occurrence prefix;
|
||
- TUI footer help now advertises every active direct function key through F5;
|
||
|
||
- in-progress Android workout loss when leaving the foreground or recreating
|
||
the Activity/process;
|
||
- missing selected-exercise recovery preserves raw partial input and reports a
|
||
specific warning; draft write/finalization failures return explicit errors;
|
||
|
||
- stale schema-v4 importer call after desktop schema v5 migration;
|
||
- stale schema-v4 guard in the PC catalog exporter;
|
||
- missing `sy` prefix support in the UUID creator;
|
||
- synchronization failures that previously surfaced only as `error=unknown`;
|
||
- Android folder-selection UX so a wrong SAF folder can be changed without
|
||
clearing application data;
|
||
- libmtp terminal output leaking into terminal rendering.
|
||
|
||
### Validation
|
||
|
||
Current validated baseline:
|
||
|
||
```text
|
||
TRAINLOG_FORMAT_V1=FROZEN
|
||
|
||
DESKTOP_SCHEMA_V11=PASS
|
||
DESKTOP_TESTS=39/39 PASS
|
||
|
||
ANDROID_BUILD=PASS
|
||
ANDROID_LOCAL_WORKFLOWS=PASS
|
||
ANDROID_LOCAL_DATABASE_V10=PASS
|
||
ANDROID_TEST_DEBUG_UNIT=44/44 PASS (real v9 fixture enabled)
|
||
ANDROID_SESSION_DRAFT_V1=PASS
|
||
ANDROID_MAX_V9_REAL_DATA_MIGRATION=PASS
|
||
ANDROID_MAX_V9_INSTALL_ADB=PASS
|
||
|
||
USB_MTP_DETECTION=PASS
|
||
MTP_HARDWARE_ROUNDTRIP=HISTORICAL_PASS
|
||
REAL_ANDROID_ARTIFACT_COPY_ROUNDTRIP=HISTORICAL_PASS
|
||
BODY_ZONES_DESKTOP_REAL_DATABASE=PASS
|
||
BODY_ZONES_ANDROID_DEVICE=PASS
|
||
|
||
ANDROID_TO_PC_MTP=HISTORICAL_PASS
|
||
PC_TO_ANDROID_MTP_PUBLISH=HISTORICAL_PASS
|
||
COMMON_SYNC_ENGINE=PASS
|
||
TRAINLOG_SYNCD=PASS
|
||
ANDROID_TRIGGERED_SYNC=PASS
|
||
ANDROID_SYNC_RECEIPT=PASS
|
||
TUI_SYNC_LOG_SHOW=PASS
|
||
BIDIRECTIONAL_SYNC_V1=PASS
|
||
MULTI_OCCURRENCE_SESSION_V2=PASS
|
||
EQUIPMENT_ASSOCIATIONS_V2=PASS
|
||
EQUIPMENT_DEFINITIONS_V1=PASS
|
||
EXERCISE_RECONCILIATION_V2=PASS
|
||
EXPLICIT_MAX_RESULTS_V1=PASS
|
||
BODY_ZONES_V1=PASS
|
||
BODY_ZONE_SYNC_V1=PASS
|
||
BODY_ZONES_DESKTOP_REAL_MIGRATION=PASS
|
||
BODY_ZONES_ANDROID_DEVICE_VALIDATION=PASS
|
||
```
|
||
|
||
For Body Zones V1, the real desktop database was backed up coherently and
|
||
migrated v10 -> v11 through the production binary. All eight pre-existing
|
||
tables compare equal row-for-row with the backup; integrity/FK checks pass and
|
||
the migration adds 32 direct relations for 20 of 23 exercises. On the Samsung
|
||
SM-G990B, the matching signed APK was installed with `adb install -r`; the real
|
||
Android database migrated v9 -> v10 with every pre-existing application row
|
||
unchanged, 32 relations for the same 20 exercises and the expected three
|
||
unclassified exercises. The Android zone/detail/filter/edit-cancel matrix and
|
||
two live PC <-> Android MTP passes completed successfully. The second pass
|
||
reported no additions or reconciliations and left every Android application
|
||
table and the semantic Body Zones companion unchanged. Scoped storage had
|
||
published the requests as exact `(N).json` collision siblings; the shared
|
||
engine now selects the newest request with the same deterministic helper used
|
||
for other Android-originated artifacts.
|
||
|
||
### Measured max v1
|
||
|
||
Added:
|
||
|
||
- explicit measured-max derivation from `max_test` sessions only;
|
||
- newest successful measured result and same-mode historical record;
|
||
- dedicated TUI measured-max history and graph;
|
||
- external working-load calculations at 60/70/80/90%;
|
||
- selectable 0.5/1/2.5/5.0 kg working-load rounding;
|
||
- direction-aware assistance measured-max semantics;
|
||
- Android `Entraînement` / `Test max` session selection;
|
||
- Android history/detail max-test identification;
|
||
- measured-max regression coverage.
|
||
|
||
No estimated 1RM, schema v6, or frozen Trainlog JSON v1 change was introduced.
|
||
|
||
### Body analytics v1
|
||
|
||
Added:
|
||
|
||
- desktop-only body analytics view;
|
||
- local height/formula estimation profile;
|
||
- circumference-based body-fat estimate;
|
||
- estimated fat and lean mass when real weight is available;
|
||
- waist/hip, shoulder/waist, and chest/waist ratios;
|
||
- arm, forearm, thigh, and calf left/right asymmetry percentages;
|
||
- weight, waist, and estimated-body-fat trend deltas;
|
||
- body analytics regression test.
|
||
|
||
Estimated analytics remain derived display values and are never persisted as
|
||
direct measurements. Android remains capture-only for this feature.
|
||
|
||
- Hid `SESSION_GENERATOR_V1` from normal UI pending V2; manual `%MAX` entry is unchanged.
|
||
- Added versioned canonical exercise display names, stale-peer-name convergence,
|
||
and the STATS_V1 query-contract preparation (no analytics implementation).
|
||
# Unreleased
|
||
|
||
- Add `TRAINING_FEEDBACK_V1`: schema v14 append-only exercise observations and
|
||
session follow-ups, Android French voice/manual capture with no audio storage,
|
||
bidirectional strict companion sync, H+ timelines, and TUI read-only display.
|