diff --git a/AGENTS.md b/AGENTS.md index c63c867..4e3e481 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,9 +6,11 @@ Trainlog consists of: - a native Android application for fast workout and body-data capture; - a Unix/Linux C17 terminal TUI for durable history, correction, analysis, - visualization, and manual synchronization. The current authorized - `TUI_NOTCURSES_V1` infrastructure tranche migrates the active rendering/input - backend from legacy ncursesw to Notcurses without changing product semantics; + visualization, and manual synchronization, using Notcurses as its completed + active rendering/input backend; +- a loopback-only local Web adapter whose Dashboard is implemented on the + 0.1.2 development branch; its Analyse, Programmes, Sessions, and Exercises + routes remain placeholders pending separate contracts; - a small user-session PC agent, `trainlog-syncd`, for Android-triggered synchronization; - versioned JSON synchronization artifacts exchanged over direct MTP. @@ -215,9 +217,12 @@ trainlog-sync-receipt-v1.json Android -> PC data uses: ```text -trainlog-mobile-export-v1.json +trainlog-mobile-export-v3.json ``` +V3 is the active completed-session snapshot. V1/V2 remain readable legacy +inputs and `TRAINLOG_FORMAT_V1` remains a separate frozen contract. + PC -> Android catalog data uses: ```text @@ -264,6 +269,19 @@ User-facing code must not intentionally return placeholders such as ## 10. Documentation +Repository documentation and publication language is: + +```text +README and canonical documentation: English +CHANGELOG and release notes: English +New or modified source comments: English +User interface: preserve its actual localization +``` + +Exact UI strings, user data, identifiers, commands, paths, protocol fields, +version/status markers, citations, and historical evidence are not translated +merely to satisfy the prose-language rule. + Canonical documents: - `README.md`; @@ -289,6 +307,14 @@ Checkpoint history belongs in Git history and `docs/reviews`; canonical documents describe the current state rather than accumulating obsolete `NEXT` sections. +Every functional change identifies the affected documentation. When relevant, +reconcile `docs/current_state.md`, `docs/roadmap.md`, and `CHANGELOG.md`; the +completion report lists updated documents or explains why none were affected. +Release publication verifies both GitHub and Forgejo notes, their English +language, and their correspondence with the exact tag independently of later +development. A requested status in prose is never sufficient evidence for a +`PASS` or `FROZEN` marker. + ## 11. Validation Before every meaningful push: diff --git a/CHANGELOG.md b/CHANGELOG.md index af9c0da..d68e892 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased — 0.1.2 +- 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, @@ -21,9 +27,11 @@ 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 current - implementation cursor remains `WEB_DASHBOARD_CHARACTERIZATION_V1`; no Web - implementation has started. +- 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 diff --git a/README.md b/README.md index 4f2f1a4..1866bba 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,9 @@ Trainlog is a local-first workout and body-data system. Trainlog Core owns business truth and canonical desktop persistence. Its native Android app is the field companion, its C17/Notcurses desktop TUI is the administration and -technical surface, and its documented future local Web sibling is the analysis, -visualization, and program/session-preparation surface. +technical surface, and its local browser Web sibling provides the implemented +Dashboard while reserving later analysis, program, session, and exercise +modules for separately contracted work. Android and desktop each own a local SQLite database. The desktop database is the canonical long-term history. Trainlog synchronizes versioned JSON artifacts @@ -16,11 +17,13 @@ over direct MTP; it never copies SQLite database files between devices. |---|---| | Android | Capture and quickly correct sets, repetitions, loads, durations, and continuous activities; reorder active and completed-session occurrences; capture feedback, J+1 follow-ups, body measurements, and AI proposals; trigger sync; show quick summaries. | | Desktop TUI | Administer, inspect, maintain, import/export, correct canonical history, and provide technical tools. | -| Local Web (planned) | Analyze and visualize canonical data; prepare programs and sessions through typed Trainlog Core services. | +| Local Web (0.1.2 development) | Display the implemented local Dashboard and persist its private layout through typed Trainlog Core/API boundaries. Analyse, Programmes, Sessions, and Exercises remain placeholders. | No interface reconstructs business truth from SQLite tables. The local Web is -a sibling adapter, not an extension of the TUI. Its loopback-only CLI/HTTP -infrastructure is implemented; its frontend and business API are not. +a sibling adapter, not an extension of the TUI. On `main`, its loopback-only +CLI/HTTP adapter, embedded frontend, read-only Dashboard API, factual tiles, +visualizations, and private layout persistence are implemented. This does not +make the other four Web routes functional or publish version 0.1.2. ## Releases @@ -127,8 +130,8 @@ updates; generating a replacement key is not a normal release procedure. ### Linux runtime dependencies -The published x86-64 TUI is dynamically linked. The current build directly -requires compatible versions of: +The published v0.1.1 x86-64 TUI is dynamically linked. Its tagged source +directly requires compatible versions of: - glibc and the GCC support runtime; - SQLite 3; @@ -137,9 +140,12 @@ requires compatible versions of: - libudev; - libmtp; - Notcurses Core; -- GNU libmicrohttpd; - the standard math library. +The current 0.1.2 development source additionally links GNU libmicrohttpd and +yyjson for the local Web adapter and Dashboard layout configuration. Those are +not retroactive requirements of the pre-Web v0.1.1 tagged source. + Distribution packages may pull additional transitive libraries, including libusb, ncursesw, unistring, gpm, libgcrypt, libgpg-error, and libdeflate. Package names and ABI versions vary by distribution; inspect the release's @@ -165,8 +171,8 @@ Desktop builds require: - a C17 compiler toolchain; - `pkg-config`; - Notcurses Core development headers; -- SQLite, libuuid, utf8proc, libudev, libmtp, and GNU libmicrohttpd development - headers; +- SQLite, libuuid, utf8proc, libudev, libmtp, GNU libmicrohttpd, and yyjson + development headers for the current development source; - Python 3 for generated sources, validators, import/export helpers, and tests. The embedded Web frontend additionally uses Node and npm at build time only. @@ -183,18 +189,25 @@ meson setup build -Dweb=enabled meson compile -C build ``` -Meson never runs `npm install` or downloads packages. The default `web=auto` +Meson never runs `npm install` or downloads packages. Run `npm ci` explicitly +for the exact lockfile before configuring a Web-enabled build. The default `web=auto` embeds the frontend when Node, npm, and the prepared `web/node_modules` are available; otherwise it preserves a desktop-only build and `trainlog -w` reports that frontend support is absent. Release builds must use `-Dweb=enabled`. `-Dweb=disabled` is the explicit desktop-only choice. Node, npm, `node_modules`, and `web/dist` are not runtime dependencies. +For an existing build directory, change the option with `meson configure +build -Dweb=enabled` (or the required value) instead of running `meson setup` +as though the directory were new. + ### Optional systemd user service for local Web development The versioned `systemd/trainlog-web.service` unit can keep `trainlog -w` -available on `127.0.0.1:8080` during an interactive user session. This is a -development convenience, not a requirement of the final Trainlog distribution. +available on `127.0.0.1:8080` during an interactive user session. Without +systemd user lingering, enabling it does not guarantee startup before login. +This is a development convenience, not a requirement of the final Trainlog +distribution. It intentionally runs the canonical user entry point `~/.local/bin/trainlog`; in a source checkout that entry point may be a symlink to the current `build/tui/trainlog` binary, but the symlink must resolve to an @@ -229,6 +242,11 @@ systemctl --user start trainlog-web journalctl --user -u trainlog-web ``` +An operator may separately configure a local nginx proxy such as +`http://trainlog.perf`. That hostname and proxy are machine-local conveniences, +not a public Trainlog domain or a runtime dependency, and Trainlog does not +configure them automatically. + Uninstalling the integration disables the unit before removing only its user configuration symlink: @@ -287,7 +305,7 @@ not contain cloud credentials and does not run `rclone`. ## Current status -As of 2026-09-15: +As of 2026-09-17: - `TRAINLOG_FORMAT_V1=PASS/FROZEN`; - desktop SQLite schema v18 and Android SQLite schema v17; @@ -301,7 +319,11 @@ As of 2026-09-15: - `TRAINLOG_AI_SESSION_DRAFT_V1=VALIDATION_PENDING` pending a real Drive plus Android-triggered bidirectional smoke test. - `WEB_FRONTEND_SHELL_V1=PASS/FROZEN` and - `TRAINLOG_WEB_V1=CONTRACT_FROZEN / IMPLEMENTATION_STARTED`. + `WEB_DASHBOARD_V1=PASS/FROZEN`; the other four Web routes remain placeholders; +- `TRAINLOG_WEB_V1=CONTRACT_FROZEN / IMPLEMENTATION_STARTED`; +- `TRAINLOG_SYNC_GAP_CONTRACT_V1=CONTRACT_FROZEN / + IMPLEMENTATION_NOT_STARTED` and the next cursor remains + `TRAINLOG_SYNC_CHARACTERIZATION_V1`. The latest executable result belongs in [current state](docs/current_state.md), not in multiple README narratives. diff --git a/docs/README.md b/docs/README.md index 5fd3a6b..f290bac 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,8 +18,8 @@ evidence and chronology. glanceable summaries, permissions, and Android interaction rules. - [Desktop TUI](tui.md) owns Notcurses navigation, correction, detailed consultation, analytics, graphs, and long-term follow-up behavior. -- [Architecture](architecture.md) owns the contract for the planned local Web - sibling, including Core/API boundaries, loopback networking, shell, +- [Architecture](architecture.md) owns the implemented and future boundaries of + the local Web sibling, including Core/API boundaries, loopback networking, shell, Dashboard, layout, build/runtime separation, and security invariants. ## Data model @@ -73,6 +73,8 @@ evidence and chronology. - [Review records](reviews/) retain historical audits, incidents, checkpoints, and validation evidence. Their status and paths are historical. - [Changelog](../CHANGELOG.md) owns chronological change history. +- [Release notes](releases/) retain reusable, tag-scoped English source text + for public GitHub and Forgejo releases. ## Ownership rule diff --git a/docs/architecture.md b/docs/architecture.md index d79a4b1..b13bd59 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -264,7 +264,8 @@ directory. The shell implements semantic Header/Body/Footer landmarks, keyboard-visible focus, responsive tile scaffolding and reduced-motion rules. Absent user/session/zone facts remain visibly unavailable. The bounded grid engine uses `react-grid-layout` 2.2.4 behind a Trainlog-owned model, adapter and -validator; ECharts remains deferred until a real visualization exists. +validator. The implemented Progression visualization loads modular ECharts +6.1.0 lazily; the BODY ZONES visualization is an original code-native SVG. The Dashboard is a canonical 12-column grid containing exactly seven V1 tiles: @@ -278,12 +279,10 @@ The Dashboard is a canonical 12-column grid containing exactly seven V1 tiles: `WEB_DASHBOARD_GRID_V1=PASS/FROZEN` supports drag and drop, horizontal and vertical resizing, tile-specific minimum/maximum sizes, automatic -reorganization, responsive projection, persistence in the next tranche, and -restoration of the Trainlog default. Dragging and resizing are enabled only by +reorganization, responsive projection, versioned private layout persistence, +and restoration of the Trainlog default. Dragging and resizing are enabled only by the explicit `Modifier l'agencement` mode. A larger tile may reveal more -information, but tile size never changes a metric's business definition. Until -`WEB_DASHBOARD_LAYOUT_V1`, saving accepts a valid draft only in current React -memory and reload restores the default. +information, but tile size never changes a metric's business definition. The single persisted source layout is the canonical desktop 12-column layout: diff --git a/docs/coding_style.md b/docs/coding_style.md index 42303c4..8fcf9a1 100644 --- a/docs/coding_style.md +++ b/docs/coding_style.md @@ -53,6 +53,10 @@ Prefer small composable functions over long functions mixing unrelated responsib ## 5. Comments +New or modified source comments are written in English. Exact external text, +protocol literals, UI strings, user data, and historical quotations retain +their required language. + Comments are required for: - public interfaces; diff --git a/docs/current_state.md b/docs/current_state.md index c34c82a..8b80dc0 100644 --- a/docs/current_state.md +++ b/docs/current_state.md @@ -12,9 +12,9 @@ Android is the field companion: it captures training and body data, preserves the active draft, receives AI proposals, triggers synchronization, and shows quick summaries. The C17/Notcurses TUI is the administration, inspection, maintenance, import/export, and technical-tooling surface. The local Web -sibling now provides its embedded application shell; its future business -surfaces will own analysis, visualization, and program/session preparation -through Trainlog Core. +sibling now provides its embedded application shell and implemented Dashboard; +its future business surfaces will own broader analysis, program/session +preparation, and exercise workflows through Trainlog Core. Trainlog Core owns business truth. The desktop SQLite database remains the canonical local source of truth and long-term history; no interface owns a @@ -157,12 +157,15 @@ the result. The Web aggregate now exposes the distinct factual snapshot through `TRAINLOG_WEB_V1` architecture, API independence, local-network boundary, browser shell, Dashboard, layout ownership, build/runtime separation, and security invariants are canonical. The CLI/local HTTP infrastructure and -embedded frontend shell are implemented: `-w`/`--web`, optional `--port`, exact -IPv4 loopback binding, `/api/v1/health`, React navigation and the persistent +embedded frontend are implemented: `-w`/`--web`, optional `--port`, exact IPv4 +loopback binding, `/api/v1/health`, React navigation, and the persistent Header/Body/Footer shell. Production assets are generated from the npm lockfile -and linked into the binary. The read-only Dashboard business snapshot and -factual Footer integration exist; no grid engine, business mutation, automatic -browser launch or layout persistence exists yet. +and linked into the binary. The read-only Dashboard uses one typed Core +snapshot, a seven-tile responsive grid, factual size-adaptive tiles, an ECharts +progression series, an original BODY ZONES SVG, and private versioned layout +persistence with optimistic conflict and CSRF/Origin protection. It provides no +business mutation or automatic browser launch. Analyse, Programmes, Sessions, +and Exercises remain explicit placeholders. ## Data semantics @@ -182,13 +185,18 @@ browser launch or layout persistence exists yet. ## Validation status -The durable commands are owned by [tests.md](tests.md). On 2026-09-17 isolated -validation passed desktop compilation, **75/75 normal Meson tests** and +The durable commands are owned by [tests.md](tests.md). At commit +`14b863eb0f159d46891f4ad5cf076b3aa0a11bba` on 2026-09-17, isolated validation +passed desktop compilation, **75/75 normal Meson tests** and **75/75 ASan/UBSan Meson tests**, Android debug assembly and **203 Android tests (199 passed, 4 skipped, 0 failed)**, the JSON validator, and the import-contract validator. The source-derived TUI `TRANSLATABLE_UI=0` check and Android resource parity also passed. Link and -diff safety checks pass in the final audit evidence. +diff safety checks passed in that checkpoint evidence. These are historical +results for that commit, not executions performed by later documentation work. +The four Android skips were the optional historical v9, v12, v13, and v14 +database-fixture migration cases. Hardware MTP, real Drive, and Android +instrumented tests were not part of that isolated run. The Dashboard Core extraction tranche passes **62/62 normal Meson tests** and **62/62 ASan/UBSan Meson tests**, including the standalone public-header and diff --git a/docs/releases/README.md b/docs/releases/README.md new file mode 100644 index 0000000..654c806 --- /dev/null +++ b/docs/releases/README.md @@ -0,0 +1,9 @@ +# Release-note sources + +This directory contains reusable English source text for public release notes. +Each file is scoped to the named immutable tag; it must describe that tag rather +than later development. GitHub and Forgejo publication must preserve the +existing release, tag, status, and assets while keeping their note bodies equal +to the corresponding source file. + +- [Trainlog v0.1.1](v0.1.1.md) diff --git a/docs/releases/v0.1.1.md b/docs/releases/v0.1.1.md new file mode 100644 index 0000000..fdafd28 --- /dev/null +++ b/docs/releases/v0.1.1.md @@ -0,0 +1,32 @@ +Trainlog v0.1.1 is the latest stable release before Web implementation began. + +## Interfaces and languages + +- French is the default interface language on Android and in the TUI, with + English selectable and a persistent local preference. +- BODY ZONE labels and synchronization states are presented locally without + changing business data or exchange formats. +- Android workflows for entering, correcting, and reordering active and + completed sessions are improved. + +## Reliability + +- Transactional corrections and regression coverage protect corrected and + synchronized sessions. +- Decimal input accepts `.` or `,`, rejects non-finite values, and preserves + intermediate editing states. +- The Android APK was built with Trainlog's durable signing identity and + verified before publication. + +## Architecture + +- The `TRAINLOG_WEB_V1` contract is frozen: the future Web interface is a local + sibling adapter built on typed Trainlog Core services. +- No Web server, frontend, or Dashboard is implemented in this release. + +## Assets + +- `trainlog-android-v0.1.1.apk`: signed Android APK. +- `trainlog-tui-linux-x86_64-v0.1.1`: dynamically linked Linux x86-64 + executable. +- `SHA256SUMS`: SHA-256 checksums for both artifacts. diff --git a/docs/roadmap.md b/docs/roadmap.md index d907e62..f17bd52 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -27,7 +27,8 @@ exchange and APP_SHELL_V1 retain their explicit manual validation/review gates. `TRAINLOG_WEB_V1=CONTRACT_FROZEN / IMPLEMENTATION_STARTED`; its local-only CLI/HTTP infrastructure, embedded frontend shell and the frozen Dashboard data contract, frozen interactive grid, versioned layout persistence and factual -tile rendering exist. Advanced visualizations remain a future slice. +tile rendering exist. The Dashboard's bounded progression and BODY ZONES +visualizations are implemented; the other four Web routes remain placeholders. ## Current cursor @@ -46,9 +47,9 @@ and it does not authorize a protocol, schema, endpoint or button change. `WEB_FRONTEND_SHELL_V1=PASS/FROZEN`. `trainlog -w` serves the embedded React, TypeScript and Vite shell with its five client routes, Catppuccin Mocha design -system, permanent Header/Footer, empty-data states and health status. The next -Dashboard tranche is partitioned below; this cursor does not authorize an -undifferentiated implementation of every Dashboard concern. +system, permanent Header/Footer, empty-data states and health status. The +Dashboard slices below are complete; this does not authorize implementation of +the remaining route placeholders. `WEB_DASHBOARD_GRID_V1=PASS/FROZEN` adds the validated 12-column desktop grid, explicit edit mode, drag/resize, keyboard alternative and derived responsive projections without persisting layout state. @@ -74,7 +75,7 @@ WEB_DASHBOARD_CHARACTERIZATION_V1 -> WEB_TUI_READ_MODEL_ADOPTION_V1 [PASS/FROZEN] -> WEB_CLI_HTTP_INFRASTRUCTURE_V1 [PASS/FROZEN] -> WEB_FRONTEND_SHELL_V1 [PASS/FROZEN] - -> WEB_DASHBOARD_V1 + -> WEB_DASHBOARD_V1 [PASS/FROZEN] ``` The Web must not start with React. Characterization proves current behavior; @@ -101,9 +102,10 @@ WEB_DASHBOARD_DATA_CONTRACT_V1 [PASS/FROZEN] -> WEB_DASHBOARD_V1_FINAL_REVIEW [PASS/FROZEN] ``` -The slice order may be refined by the next contract, but it must preserve the -existing Core ownership, keep visual layout outside business SQLite and frozen -formats, and specify Activité/Progression before implementing those metrics. +The completed slice order preserves Core ownership, keeps visual layout outside +business SQLite and frozen formats, and specifies Activity/Progression before +rendering those metrics. Later Dashboard evolution must preserve those frozen +boundaries. `WEB_NEXT_MODULE_SELECTION_V1` remains a future Web documentary cursor. The current roadmap does not yet establish a contract order between Analyse, Programmes, @@ -117,8 +119,9 @@ 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. No implementation lot is -started. `WEB_DASHBOARD_V1=PASS/FROZEN` remains closed and unchanged. +orchestrator/report, Web API, then button/refresh. The environment/test lot is +complete; no production synchronization implementation lot is started. +`WEB_DASHBOARD_V1=PASS/FROZEN` remains closed and unchanged. ### Gym catalog V1 diff --git a/docs/tests.md b/docs/tests.md index f08c48b..229849c 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -396,7 +396,7 @@ point for the desktop and Android validation needed by synchronization work: ```bash python3 tools/validate_sync_isolated.py --suite preflight python3 tools/validate_sync_isolated.py --suite smoke -python3 tools/validate_sync_isolated.py --suite full +python3 tools/validate_sync_isolated.py --suite full --jdk /usr/lib/jvm/java-17-openjdk ``` Use `--jdk /absolute/jdk17/home` when auto-detection is unsuitable and @@ -441,6 +441,13 @@ harness terminates only process groups that it started, waits before forced termination, never stops a pre-existing Gradle daemon or Trainlog service, and refuses cleanup outside its exact root or across a symlink. +At the 2026-09-17 reference checkpoint, the Android total retained four skips +because optional historical database fixtures were unavailable: one v9, one +v12, one v13, and one v14 migration-fixture case. These are explicit fixture +coverage gaps, not passing migration executions. The isolated harness does not +run hardware MTP, real Drive, or Android instrumented tests; those remain +separate validation classes. + Stable-release validation additionally builds the signed release variant and checks the packaged product versions and binary linkage: