docs apply STE100 fixes to prose comments

Documentation-only STE100 compliance pass across the web, presenter, and bin layers. Split semicolon-joined prose into separate sentences, rewrite passive voice with a known agent into active voice, remove a phrasal verb and a nominalized subject, and repair a garbled comment. Also correct a stale progress-page doc that described a search that does not exist, and align the cancel-dialog copy with 'cannot'. No behavior change.

Commit
8e7b7cd03150fb56c4fa4ef48b7fb716cb09a196
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
bin/main.ml
index 2563591f..6bc072b5 100644..100644
@@ -7,8 +7,8 @@
7 7 [local_db/] is excluded from the dune build and watch tree, so
8 8 the database and its journal never retrigger [dune -w].
9 9 - HITO_SECRET Secret for signing session cookies and CSRF tokens. When
10 Removed: unset, a random secret is generated for this run only, so
11 Removed: sessions do not survive a restart. Set it in production.
10 Added: unset, the server generates a random secret for this run only,
11 Added: so sessions do not survive a restart. Set it in production.
12 12 - HITO_PORT TCP port. Default: 8080
13 13 - HITO_VERSION Deployment commit identifier shown in the page footer. Defaults
14 14 to "development" outside a deployment.
bin/seed.ml
index b16c6c86..0bc47873 100644..100644
@@ -10,12 +10,13 @@
10 10 (* The trainee's real Hevy export, imported as personal history through the
11 11 Workout_import use case rather than fabricated. The use case gates what the
12 12 core ever sees: only a set whose source exercise maps to the curated catalog
13 Removed: promotes to canonical evidence. Warmups, cardio, and bodyweight rows without
14 Removed: a load are dropped by the parser as warnings. A drop set is discarded the way
15 Removed: a warmup is — HD1 keeps only the drive to failure, never the strip rounds —
16 Removed: so it neither promotes nor blocks. An unmapped exercise blocks only itself.
17 Removed: All of that is doctrine, not loss: HD1 favours a curated catalog over
18 Removed: novelty, and a deviation is retained, never guessed at. *)
13 Added: promotes to canonical evidence. The parser drops warmups, cardio, and
14 Added: bodyweight rows without a load as warnings. The parser discards a drop set
15 Added: the way it discards a warmup, because HD1 keeps only the drive to failure,
16 Added: never the strip rounds. A drop set therefore neither promotes nor blocks. An
17 Added: unmapped exercise blocks only itself. All of that is doctrine, not loss: HD1
18 Added: favours a curated catalog over novelty, and the app retains a deviation
19 Added: rather than guessing at it. *)
19 20
20 21 (* Hevy datetimes are local wall time. The export was recorded at UTC+2. *)
21 22 let utc_offset_seconds = 7200
@@ -25,8 +26,8 @@
25 26 unmapped, so its workout blocks on [Unmapped_exercise] rather than promoting
26 27 a guess — "focus over novelty" (HD1, "The Routine"). Trap-bar and Romanian
27 28 deadlifts, the machine squat, machine chest and shoulder presses, and the
28 Removed: flat barbell bench have no Standard catalog entry, so they are left unmapped
29 Removed: on purpose. *)
29 Added: flat barbell bench have no Standard catalog entry, so the table leaves them
30 Added: unmapped on purpose. *)
30 31 let catalog_of_source name =
31 32 let id =
32 33 match name with
@@ -80,8 +81,8 @@
80 81
81 82 (* Import [csv_path] for [trainee_id] as one batch: store it, map every source
82 83 name that has a catalog equivalent, acknowledge the normal sets of any
83 Removed: workout that has one, then promote the whole batch. Promotion is partial —
84 Removed: a blocked workout is left in the batch for later review, never forced. *)
84 Added: workout that has one, then promote the whole batch. Promotion is partial. The
85 Added: batch keeps a blocked workout for later review and never forces it. *)
85 86 let import_csv repo trainee_id ~csv_path =
86 87 let source = read_file csv_path in
87 88 let fingerprint = Digest.to_hex (Digest.string source) in
@@ -139,7 +140,8 @@
139 140 (List.length result.WI.already_promoted)
140 141 (List.length result.WI.blocked)
141 142
142 Removed: (* Idempotent: skip the import when the trainee already has promoted records. *)
143 Added: (* Idempotent. The function skips the import when the trainee already has
144 Added: promoted records. *)
143 145 let seed_history repo trainee_id ~csv_path =
144 146 Service.make ~repo |> fun service ->
145 147 Service.imported_records service trainee_id >>= fun records ->
bin/seed.mli
index b3541e9b..e9e426e2 100644..100644
@@ -8,10 +8,10 @@
8 8 unit Lwt.t
9 9 (** Register [blendux] with [password] and select the Ideal Routine, or reuse
10 10 the existing account. Then, when the account has no promoted import records,
11 Removed: import the Hevy export at [csv_path] as personal history: parse it, map each
12 Removed: exercise the curated catalog names, acknowledge normal sets, and promote the
13 Removed: batch. Blocked workouts — drop sets, or exercises outside the catalog — are
14 Removed: left in the batch for review, never forced. When no file exists at
15 Removed: [csv_path] the import is skipped, so a deployment that ships no export still
16 Removed: seeds the account and routine. Exits the process on a malformed seed
17 Removed: username or an import failure. *)
11 Added: import the Hevy export at [csv_path] as personal history. The import parses
12 Added: the export, maps each exercise the curated catalog names, acknowledges
13 Added: normal sets, and promotes the batch. The batch keeps a blocked workout for
14 Added: review and never forces it. A drop set or an exercise outside the catalog
15 Added: blocks a workout. When no file exists at [csv_path] the import is skipped,
16 Added: so a deployment that ships no export still seeds the account and routine.
17 Added: Exits the process on a malformed seed username or an import failure. *)
lib/presenter/pages.mli
index a82b823b..449e8f23 100644..100644
@@ -82,9 +82,8 @@
82 82 viewer:View_model.Viewer.t ->
83 83 View_model.Progress_page.t ->
84 84 page
85 Removed: (** The per-exercise progress page: a no-JS exercise search that reloads with
86 Removed: the chosen exercise's dual-axis line chart (weight on the left, reps on the
87 Removed: right), from the merged native and imported history. *)
85 Added: (** The per-exercise progress page. One dual-axis line chart per exercise with
86 Added: at least two observations in the merged native and imported history. *)
88 87
89 88 val profile :
90 89 Dream.request ->
lib/presenter/pages_routine.ml
index 1d1de275..3a480885 100644..100644
@@ -92,7 +92,7 @@
92 92 [
93 93 txt
94 94 "Heavy Duty grows muscle during recovery, not in the gym. \
95 Removed: Training early can cut into it. This is recorded as an \
95 Added: Training early can reduce it. The app records this as an \
96 96 override.";
97 97 ];
98 98 tag "div"
lib/presenter/pages_workout.ml
index ef4518b2..42077072 100644..100644
@@ -379,7 +379,7 @@
379 379 ]
380 380 [
381 381 tag "h2" [] [ txt "Cancel logging this workout?" ];
382 Removed: tag "p" [] [ txt "This action can not be undone." ];
382 Added: tag "p" [] [ txt "This action cannot be undone." ];
383 383 tag "div"
384 384 [ class_ "button-group" ]
385 385 [
lib/web/handlers_current_workout.ml
index c7aebcc7..cc318f06 100644..100644
@@ -56,8 +56,9 @@
56 56
57 57 (* The response after a successful record or correction: a POST-redirect-GET
58 58 that flashes [message] and reloads the workout. Record and correction
59 Removed: submits navigate natively (full page), which guarantees the reloaded view
60 Removed: reflects exactly what was saved — no client swap that could race. *)
59 Added: submits navigate natively with a full page. The full page guarantees that
60 Added: the reloaded view reflects exactly what the app saved, with no client swap
61 Added: that could race. *)
61 62 let saved _t _trainee request message =
62 63 redirect_with_flash request
63 64 (Dream_html.path_attr Dream_html.HTML.href Routes.workout)
lib/web/handlers_import.ml
index d62552f0..094cd8ed 100644..100644
@@ -75,7 +75,7 @@
75 75 { View_model.Viewer.username = Trainee.username_to_string trainee.username }
76 76
77 77 (* A distinct batch id even when a duplicate override re-imports the same
78 Removed: source: the fingerprint prefix, the import time in seconds, and a random
78 Added: source. The fingerprint prefix, the import time in seconds, and a random
79 79 suffix keep two imports of one export apart, so an override never
80 80 overwrites the original batch. *)
81 81 let generate_batch_id ~fingerprint ~imported_at =
lib/web/handlers_kit.ml
index 3d55d5b2..443fa960 100644..100644
@@ -49,9 +49,9 @@
49 49
50 50 Every domain and service error becomes a user-facing sentence here, so a
51 51 handler renders a message rather than deciding its wording. One module owns
52 Removed: the phrasing, and adding an error variant surfaces as a missing case. The
53 Removed: core's [pp] functions are debugging output and are not used for copy: a
54 Removed: wording change must never reach the entity layer. *)
52 Added: the phrasing. When you add an error variant, the compiler surfaces a
53 Added: missing case. The core's [pp] functions are debugging output and are not
54 Added: used for copy: a wording change must never reach the entity layer. *)
55 55 module Present = struct
56 56 let form_invalid = "The submitted form is not valid."
57 57
lib/web/handlers_logbook.ml
index b8671fe6..d242d7fb 100644..100644
@@ -11,9 +11,9 @@
11 11
12 12 let field name fields = List.assoc_opt name fields
13 13
14 Removed: (* Each factor is its own radio group. A group left untouched is absent from
15 Removed: the post, and a value outside the three choices is treated the same way, so
16 Removed: a partial report needs no separate Skip. *)
14 Added: (* Each factor is its own radio group. An untouched group is absent from the
15 Added: post. A value outside the three choices counts the same way, so a partial
16 Added: report needs no separate Skip. *)
17 17 let feedback_signals fields =
18 18 let level = function
19 19 | "worse" -> Some Feedback.Worse_than_usual
@@ -46,9 +46,9 @@
46 46 | 2 -> if is_leap year then 29 else 28
47 47 | _ -> 30
48 48
49 Removed: (* The weekday of a given UTC date, 0 = Monday .. 6 = Sunday. Uses Howard
50 Removed: Hinnant's day-count from the epoch, so it needs no timezone-aware libc call
51 Removed: ([timegm] is not in the stdlib). *)
49 Added: (* The weekday of a given UTC date, 0 = Monday .. 6 = Sunday. This uses Howard
50 Added: Hinnant's day-count from the epoch. The count needs no timezone-aware libc
51 Added: call, because [timegm] is not in the stdlib. *)
52 52 let monday_first_weekday ~year ~month ~day =
53 53 let y = if month <= 2 then year - 1 else year in
54 54 let era = (if y >= 0 then y else y - 399) / 400 in
@@ -177,7 +177,7 @@
177 177 (* A promoted import: canonical evidence, read-only. It carries no
178 178 prescription, so the native progress columns do not apply. Its detail lists
179 179 the imported efforts verbatim. It still feeds progress per exercise through
180 Removed: the service; the logbook only shows it. *)
180 Added: the service. The logbook only shows it. *)
181 181 let imported_effort_view ~history (o : Evidence.Observation.t) :
182 182 View_model.Imported_effort.t =
183 183 let effort = Evidence.Observation.effort o in
@@ -197,8 +197,9 @@
197 197
198 198 (* Build one imported entry. Each imported effort carries the progress since
199 199 that exercise was last performed, compared against the merged native and
200 Removed: imported history the service supplies. History is fetched once per distinct
201 Removed: exercise in the record, so a workout of repeated exercises stays cheap. *)
200 Added: imported history the service supplies. The service fetches history once per
201 Added: distinct exercise in the record, so a workout of repeated exercises stays
202 Added: cheap. *)
202 203 let imported_entry_view t trainee (record : Repository.imported_record) :
203 204 View_model.Logbook_entry.t Lwt.t =
204 205 let started =
@@ -273,7 +274,7 @@
273 274 in
274 275 let year = query_int "year" (now_tm.Unix.tm_year + 1900) in
275 276 let month = clamp 1 12 (query_int "month" (now_tm.Unix.tm_mon + 1)) in
276 Removed: (* Only the chosen month's entries fill the table; the calendar's year range
277 Added: (* Only the chosen month's entries fill the table. The calendar's year range
277 278 still spans all history. *)
278 279 let in_month (e : View_model.Logbook_entry.t) =
279 280 let tm = Unix.gmtime (float_of_int e.at_unix) in
@@ -314,9 +315,9 @@
314 315 | _ -> false)
315 316 ~feedback_open ?delete_record ?expanded_record records)
316 317
317 Removed: (* One post saves the whole report. Nothing is stored before Submit, so there
318 Removed: is no partial state to keep or discard. An empty submission is a mistake
319 Removed: worth naming rather than an empty report worth storing. *)
318 Added: (* One post saves the whole report. The app stores nothing before Submit, so
319 Added: there is no partial state to keep or discard. An empty submission is a
320 Added: mistake worth naming rather than an empty report worth storing. *)
320 321 let record_feedback t trainee request =
321 322 let back = Dream_html.path_attr Dream_html.HTML.href Routes.logbook in
322 323 Dream.form request >>= function
@@ -430,14 +431,10 @@
430 431 (Dream_html.path_attr Dream_html.HTML.href Routes.logbook)
431 432 "That workout log is no longer available.")
432 433
433 Removed: (* The per-exercise progress page. The search submits a GET with the exercise
434 Removed: name; resolve it to a catalog entry, then plot its merged native and
435 Removed: imported history. A chart needs at least two observations to draw a line;
436 Removed: fewer reports as insufficient. *)
437 434 (* The progress page. One dual-axis line chart per exercise that has at least
438 Removed: two observations in the merged native and imported history; exercises with
439 Removed: too little to draw a line are omitted. No search — the page shows every
440 Removed: chartable exercise. *)
435 Added: two observations in the merged native and imported history. Exercises with
436 Added: too little to draw a line are omitted. There is no search. The page shows
437 Added: every chartable exercise. *)
441 438 let progress t trainee request =
442 439 let viewer =
443 440 {
lib/web/workout_client.ml
index 66fa32eb..624660dc 100644..100644
@@ -73,8 +73,8 @@
73 73 | Some started -> (
74 74 (* Epoch seconds exceed js_of_ocaml's 31-bit [int] range, so the
75 75 start and the current time are kept as floats. Only the small
76 Removed: elapsed difference is narrowed to an [int]. Doing the subtraction
77 Removed: in [int] would overflow and yield a wrong count. *)
76 Added: elapsed difference is narrowed to an [int]. If you subtract in
77 Added: [int], the value overflows and yields a wrong count. *)
78 78 let started =
79 79 try float_of_string (String.trim (Js.to_string started))
80 80 with _ -> 0.
@@ -535,8 +535,8 @@
535 535 Js._true))
536 536 Js._false
537 537 |> ignore;
538 Removed: (* Mark the document as script-enhanced so CSS can hide no-JS fallbacks such
539 Removed: in CSS. Set only once the client runs, so
538 Added: (* Mark the document as script-enhanced so the CSS can hide the no-JS
539 Added: fallbacks. Set only once the client runs, so
540 540 a no-JS visitor keeps every fallback. *)
541 541 document##.documentElement##setAttribute
542 542 (Js.string "data-hito-js") (Js.string "on");