refactor Lift Feedback out of Evidence

Evidence's own header says "stimuli, workouts, and history": what the body did. A subjective self-report is what the trainee said. The two make different kinds of claim, so give Feedback its own core module. Nothing in the module changes; consumers name Feedback instead of Evidence.Feedback. Service had internal submodules named Routines and Feedback that now shadow the core modules of the same names. Rename them Routine_flow and Self_report so a later edit inside Service cannot silently bind the wrong module.

Commit
d1f72551c224a8dc6c383283db9d5bdea0652a52
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
ARCHITECTURE.org
index 7ddefeab..6a623955 100644..100644
@@ -108,7 +108,9 @@
108 108 |-------------+----------------+--------------------------------|
109 109 | vocabulary | =Exercise= | what movements exist, and pair |
110 110 | normative | =Prescription= | what should be done |
111 Added: | authored | =Routines= | the plans the book supplies |
111 112 | factual | =Evidence= | what was done |
113 Added: | reported | =Feedback= | what the trainee said |
112 114 | inferential | =Progress= | what that means |
113 115
114 116 =Recovery= straddles the divide deliberately: it measures a fact (elapsed rest)
@@ -159,7 +161,7 @@
159 161 hito.app Trainee · Repository · Password_hash (ports) · Service · Catalog · Workout_import
160 162 | identity, the ports, recovery policy, Lwt — no database
161 163 v
162 Removed: hito.core Exercise · Recovery · Prescription · Routines · Evidence · Progress
164 Added: hito.core Exercise · Recovery · Prescription · Routines · Feedback · Evidence · Progress
163 165 pure domain: no framework, no database, no serialization
164 166 #+end_src
165 167
@@ -173,7 +175,7 @@
173 175 composition root, the one file that names both an adapter and the use case it
174 176 plugs into.
175 177
176 Removed: The core is six modules, unwrapped (=wrapped false=), so they are referred to
178 Added: The core is seven modules, unwrapped (=wrapped false=), so they are referred to
177 179 bare: =Prescription.Stimulus=, =Evidence.Workout=, =Evidence.Log=. It has no
178 180 dependency on Lwt, Caqti, Dream, or any serializer, and gaining one would be a
179 181 design failure rather than a convenience.
@@ -254,7 +256,11 @@
254 256 a prescription or clearance. =Progress= judges observations and therefore
255 257 does not know their provenance.
256 258
257 Removed: =Feedback= is a typed vocabulary for the two self-reports HD1 grounds —
259 Added: ** Feedback — the self-report
260 Added:
261 Added: =Feedback= is its own module, not part of =Evidence=, because the two make
262 Added: different kinds of claim: =Evidence= records what the body did, =Feedback= what
263 Added: the trainee said. It is a typed vocabulary for the two self-reports HD1 grounds —
258 264 motivation (chapter 6, and a named overtraining symptom) and perceived
259 265 difficulty ("the weights feel much heavier than usual") — with duplicate
260 266 categories rejected. Each carries a relative reading, not an absolute score:
lib/app/repository.ml
index f52c9221..9d00c0b0 100644..100644
@@ -70,8 +70,8 @@
70 70 val replace : t -> Trainee.id -> record -> bool Lwt.t
71 71 val log : t -> Trainee.id -> Evidence.Log.t Lwt.t
72 72 val history : t -> Trainee.id -> record list Lwt.t
73 Removed: val save_feedback : t -> Trainee.id -> Evidence.Feedback.t -> unit Lwt.t
74 Removed: val feedback : t -> Trainee.id -> Evidence.Feedback.t list Lwt.t
73 Added: val save_feedback : t -> Trainee.id -> Feedback.t -> unit Lwt.t
74 Added: val feedback : t -> Trainee.id -> Feedback.t list Lwt.t
75 75
76 76 val save_app_feedback :
77 77 t ->
lib/app/repository.mli
index 9a137bac..253a6a48 100644..100644
@@ -118,11 +118,11 @@
118 118
119 119 (** {2 Subjective feedback} *)
120 120
121 Removed: val save_feedback : t -> Trainee.id -> Evidence.Feedback.t -> unit Lwt.t
121 Added: val save_feedback : t -> Trainee.id -> Feedback.t -> unit Lwt.t
122 122 (** Store a subjective feedback report. Feedback is a standalone observation,
123 123 not tied to a workout: a trainee may report it at any time. *)
124 124
125 Removed: val feedback : t -> Trainee.id -> Evidence.Feedback.t list Lwt.t
125 Added: val feedback : t -> Trainee.id -> Feedback.t list Lwt.t
126 126 (** Stored feedback reports, most recent first. *)
127 127
128 128 val save_app_feedback :
lib/app/service.ml
index 61251038..0cfd5a29 100644..100644
@@ -167,7 +167,7 @@
167 167 end
168 168
169 169 (* --- routines and selection --- *)
170 Removed: module Routines = struct
170 Added: module Routine_flow = struct
171 171 let list_routines t = R.list_routines t.repo
172 172
173 173 let select_routine t trainee id =
@@ -342,11 +342,11 @@
342 342 end
343 343
344 344 (* --- subjective feedback --- *)
345 Removed: module Feedback = struct
345 Added: module Self_report = struct
346 346 let record t trainee ~reported_at signals =
347 Removed: match Evidence.Feedback.make ~reported_at signals with
347 Added: match Feedback.make ~reported_at signals with
348 348 | report -> R.save_feedback t.repo trainee report >|= fun () -> Ok report
349 Removed: | exception Evidence.Feedback.Invalid error -> Lwt.return (Error error)
349 Added: | exception Feedback.Invalid error -> Lwt.return (Error error)
350 350
351 351 let list t trainee = R.feedback t.repo trainee
352 352 end
@@ -491,11 +491,11 @@
491 491 let find_trainee = Accounts.find_trainee
492 492 let change_username = Accounts.change_username
493 493 let change_password = Accounts.change_password
494 Removed: let list_routines = Routines.list_routines
495 Removed: let select_routine = Routines.select_routine
496 Removed: let active_routine = Routines.active_routine
497 Removed: let next_workout = Routines.next_workout
498 Removed: let readiness = Routines.readiness
494 Added: let list_routines = Routine_flow.list_routines
495 Added: let select_routine = Routine_flow.select_routine
496 Added: let active_routine = Routine_flow.active_routine
497 Added: let next_workout = Routine_flow.next_workout
498 Added: let readiness = Routine_flow.readiness
499 499 let begin_workout = Workouts.begin_workout
500 500 let in_progress = Workouts.in_progress
501 501 let log = Workouts.log
@@ -509,8 +509,8 @@
509 509 let workout_log = Records.workout_log
510 510 let progress = Assessment.progress
511 511 let diagnostics = Assessment.diagnostics
512 Removed: let record_feedback = Feedback.record
513 Removed: let feedback = Feedback.list
512 Added: let record_feedback = Self_report.record
513 Added: let feedback = Self_report.list
514 514 let record_app_feedback = App_feedback.record
515 515 let app_feedback = App_feedback.list
516 516 let upvote_app_feedback = App_feedback.upvote
lib/app/service.mli
index 58316da8..04fc7873 100644..100644
@@ -190,13 +190,13 @@
190 190 t ->
191 191 Trainee.id ->
192 192 reported_at:Recovery.timestamp ->
193 Removed: Evidence.Feedback.signal list ->
194 Removed: (Evidence.Feedback.t, Evidence.Feedback.error) result Lwt.t
193 Added: Feedback.signal list ->
194 Added: (Feedback.t, Feedback.error) result Lwt.t
195 195 (** Store a subjective feedback report. [Error] when a signal category
196 196 repeats. Feedback is standalone: a trainee may report it at any time,
197 197 independent of a workout. *)
198 198
199 Removed: val feedback : t -> Trainee.id -> Evidence.Feedback.t list Lwt.t
199 Added: val feedback : t -> Trainee.id -> Feedback.t list Lwt.t
200 200 (** Stored feedback reports, most recent first. *)
201 201
202 202 (** {2 Application feedback} *)
lib/core/dune
index e0a0f578..50abe08f 100644..100644
@@ -5,5 +5,5 @@
5 5 (library
6 6 (name hito_core)
7 7 (public_name hito.core)
8 Removed: (modules exercise recovery prescription routines evidence progress)
8 Added: (modules exercise recovery prescription routines feedback evidence progress)
9 9 (wrapped false))
lib/core/evidence.ml
index 698bc41c..daeac9cd 100644..100644
@@ -66,39 +66,6 @@
66 66 Format.fprintf ppf "%a then %a" Effort.pp first Effort.pp second
67 67 end
68 68
69 Removed: module Feedback = struct
70 Removed: type level = Worse_than_usual | As_usual | Better_than_usual
71 Removed:
72 Removed: let pp_level ppf = function
73 Removed: | Worse_than_usual -> Format.pp_print_string ppf "worse than usual"
74 Removed: | As_usual -> Format.pp_print_string ppf "as usual"
75 Removed: | Better_than_usual -> Format.pp_print_string ppf "better than usual"
76 Removed:
77 Removed: type signal = Motivation of level | Difficulty of level
78 Removed: type t = { reported_at : Recovery.timestamp; signals : signal list }
79 Removed: type error = Duplicate_signal of signal
80 Removed:
81 Removed: exception Invalid of error
82 Removed:
83 Removed: let same_category left right =
84 Removed: match (left, right) with
85 Removed: | Motivation _, Motivation _ | Difficulty _, Difficulty _ -> true
86 Removed: | _ -> false
87 Removed:
88 Removed: let make ~reported_at signals =
89 Removed: let rec validate seen = function
90 Removed: | [] -> { reported_at; signals }
91 Removed: | signal :: rest ->
92 Removed: if List.exists (same_category signal) seen then
93 Removed: raise (Invalid (Duplicate_signal signal))
94 Removed: else validate (signal :: seen) rest
95 Removed: in
96 Removed: validate [] signals
97 Removed:
98 Removed: let reported_at t = t.reported_at
99 Removed: let signals t = t.signals
100 Removed: end
101 Removed:
102 69 module Workout = struct
103 70 type shape = As_single | As_pair
104 71 type completeness = Complete | Incomplete
lib/core/evidence.mli
index 03bd9b59..8d16587a 100644..100644
@@ -53,44 +53,6 @@
53 53 val pp : Format.formatter -> t -> unit
54 54 end
55 55
56 Removed: (** Typed signals reported at a point in time. *)
57 Removed: module Feedback : sig
58 Removed: type level =
59 Removed: | Worse_than_usual
60 Removed: | As_usual
61 Removed: | Better_than_usual
62 Removed: (** A self-report relative to the trainee's usual baseline, not an
63 Removed: absolute score. HD1 frames both signals this way — Difficulty is
64 Removed: "the weights feel much heavier than usual". Three values resist the
65 Removed: false precision of a finer scale, in the spirit of HD1's refusal of
66 Removed: spurious measurement gradations. [Worse_than_usual] is the
67 Removed: concerning direction for both signals. *)
68 Removed:
69 Removed: val pp_level : Format.formatter -> level -> unit
70 Removed:
71 Removed: type signal =
72 Removed: | Motivation of level
73 Removed: | Difficulty of level
74 Removed: (** The only self-reports HD1 grounds. Motivation is HD1 chapter 6, and
75 Removed: a halt in it is a recognized overtraining symptom ("with those who
76 Removed: chronically overtrain, such a disinclination is easy to
77 Removed: understand"). Difficulty is HD1's "the weights feel much heavier
78 Removed: than usual" — a depletion symptom. HD1 gauges recovery by time and
79 Removed: by effect (a stall or decompensation), not by a wider battery of
80 Removed: wellness proxies, so none are modeled. *)
81 Removed:
82 Removed: type t
83 Removed: type error = Duplicate_signal of signal
84 Removed:
85 Removed: exception Invalid of error
86 Removed:
87 Removed: val make : reported_at:Recovery.timestamp -> signal list -> t
88 Removed: (** Raises [Invalid] when feedback repeats a signal category. *)
89 Removed:
90 Removed: val reported_at : t -> Recovery.timestamp
91 Removed: val signals : t -> signal list
92 Removed: end
93 Removed:
94 56 (** A prescribed workout as observed through its whole life. A workout may be
95 57 edited before or after it ends. The log records what happened, so
96 58 [add_stimulus], [replace_stimulus], and [record_at] deliberately accept an
lib/core/feedback.ml
index 00000000..0da63359 000000..100644
@@ -0,0 +1,33 @@
1 Added: (* Subjective self-reports, kept apart from Evidence: what the trainee said,
2 Added: not what the body did. *)
3 Added:
4 Added: type level = Worse_than_usual | As_usual | Better_than_usual
5 Added:
6 Added: let pp_level ppf = function
7 Added: | Worse_than_usual -> Format.pp_print_string ppf "worse than usual"
8 Added: | As_usual -> Format.pp_print_string ppf "as usual"
9 Added: | Better_than_usual -> Format.pp_print_string ppf "better than usual"
10 Added:
11 Added: type signal = Motivation of level | Difficulty of level
12 Added: type t = { reported_at : Recovery.timestamp; signals : signal list }
13 Added: type error = Duplicate_signal of signal
14 Added:
15 Added: exception Invalid of error
16 Added:
17 Added: let same_category left right =
18 Added: match (left, right) with
19 Added: | Motivation _, Motivation _ | Difficulty _, Difficulty _ -> true
20 Added: | _ -> false
21 Added:
22 Added: let make ~reported_at signals =
23 Added: let rec validate seen = function
24 Added: | [] -> { reported_at; signals }
25 Added: | signal :: rest ->
26 Added: if List.exists (same_category signal) seen then
27 Added: raise (Invalid (Duplicate_signal signal))
28 Added: else validate (signal :: seen) rest
29 Added: in
30 Added: validate [] signals
31 Added:
32 Added: let reported_at t = t.reported_at
33 Added: let signals t = t.signals
lib/core/feedback.mli
index 00000000..fffae8ac 000000..100644
@@ -0,0 +1,38 @@
1 Added: (** Subjective self-reports at a point in time: what the trainee said, not what
2 Added: the body did. HD1 grounds two, and gauges recovery by time and by effect
3 Added: rather than by a wider battery of wellness proxies. *)
4 Added:
5 Added: type level =
6 Added: | Worse_than_usual
7 Added: | As_usual
8 Added: | Better_than_usual
9 Added: (** A self-report relative to the trainee's usual baseline, not an
10 Added: absolute score. HD1 frames both signals this way — Difficulty is "the
11 Added: weights feel much heavier than usual". Three values resist the false
12 Added: precision of a finer scale, in the spirit of HD1's refusal of spurious
13 Added: measurement gradations. [Worse_than_usual] is the concerning direction
14 Added: for both signals. *)
15 Added:
16 Added: val pp_level : Format.formatter -> level -> unit
17 Added:
18 Added: type signal =
19 Added: | Motivation of level
20 Added: | Difficulty of level
21 Added: (** The only self-reports HD1 grounds. Motivation is HD1 chapter 6, and a
22 Added: halt in it is a recognized overtraining symptom ("with those who
23 Added: chronically overtrain, such a disinclination is easy to understand").
24 Added: Difficulty is HD1's "the weights feel much heavier than usual" — a
25 Added: depletion symptom. HD1 gauges recovery by time and by effect (a stall
26 Added: or decompensation), not by a wider battery of wellness proxies, so
27 Added: none are modeled. *)
28 Added:
29 Added: type t
30 Added: type error = Duplicate_signal of signal
31 Added:
32 Added: exception Invalid of error
33 Added:
34 Added: val make : reported_at:Recovery.timestamp -> signal list -> t
35 Added: (** Raises [Invalid] when feedback repeats a signal category. *)
36 Added:
37 Added: val reported_at : t -> Recovery.timestamp
38 Added: val signals : t -> signal list
lib/persistence/codec.ml
index 13e896cd..77102ac5 100644..100644
@@ -323,18 +323,18 @@
323 323
324 324 (* --- subjective feedback --- *)
325 325
326 Removed: let level_code : Evidence.Feedback.level -> string = function
326 Added: let level_code : Feedback.level -> string = function
327 327 | Worse_than_usual -> "worse"
328 328 | As_usual -> "usual"
329 329 | Better_than_usual -> "better"
330 330
331 331 let level_of_code = function
332 Removed: | "worse" | "1" | "2" -> Ok Evidence.Feedback.Worse_than_usual
333 Removed: | "usual" | "3" -> Ok Evidence.Feedback.As_usual
334 Removed: | "better" | "4" | "5" -> Ok Evidence.Feedback.Better_than_usual
332 Added: | "worse" | "1" | "2" -> Ok Feedback.Worse_than_usual
333 Added: | "usual" | "3" -> Ok Feedback.As_usual
334 Added: | "better" | "4" | "5" -> Ok Feedback.Better_than_usual
335 335 | code -> Error (Malformed (Printf.sprintf "level %S" code))
336 336
337 Removed: let signal_code : Evidence.Feedback.signal -> string = function
337 Added: let signal_code : Feedback.signal -> string = function
338 338 | Motivation l -> "motivation:" ^ level_code l
339 339 | Difficulty l -> "difficulty:" ^ level_code l
340 340
@@ -344,14 +344,14 @@
344 344 Ok (make l)
345 345 in
346 346 match String.split_on_char ':' code with
347 Removed: | [ "motivation"; l ] -> leveled (fun l -> Evidence.Feedback.Motivation l) l
348 Removed: | [ "difficulty"; l ] -> leveled (fun l -> Evidence.Feedback.Difficulty l) l
347 Added: | [ "motivation"; l ] -> leveled (fun l -> Feedback.Motivation l) l
348 Added: | [ "difficulty"; l ] -> leveled (fun l -> Feedback.Difficulty l) l
349 349 | _ -> Error (Malformed (Printf.sprintf "signal %S" code))
350 350
351 351 let encode_feedback report =
352 Removed: let reported_at = Timestamp.encode (Evidence.Feedback.reported_at report) in
352 Added: let reported_at = Timestamp.encode (Feedback.reported_at report) in
353 353 let signals =
354 Removed: String.concat "," (List.map signal_code (Evidence.Feedback.signals report))
354 Added: String.concat "," (List.map signal_code (Feedback.signals report))
355 355 in
356 356 Printf.sprintf "%s\t%s" reported_at signals
357 357
@@ -373,5 +373,5 @@
373 373 | Error _ as e -> e)
374 374 in
375 375 let* signals = go [] codes in
376 Removed: Ok (Evidence.Feedback.make ~reported_at signals))
376 Added: Ok (Feedback.make ~reported_at signals))
377 377 | _ -> Error (Malformed "feedback arity")
lib/persistence/codec.mli
index 9dfe1492..74e4e362 100644..100644
@@ -31,8 +31,8 @@
31 31 (Evidence.Workout.t, error) result
32 32 (** Rebuilds a workout, resolving its prescription through [find_routine]. *)
33 33
34 Removed: val encode_feedback : Evidence.Feedback.t -> string
34 Added: val encode_feedback : Feedback.t -> string
35 35 (** A stable, single-string encoding of a subjective feedback report. *)
36 36
37 Removed: val decode_feedback : string -> (Evidence.Feedback.t, error) result
37 Added: val decode_feedback : string -> (Feedback.t, error) result
38 38 (** Rebuilds a feedback report from its encoding. *)
lib/presenter/view_model.ml
index 560b4db6..0b7089bb 100644..100644
@@ -39,8 +39,8 @@
39 39 presenter graphs. [None] where the report gave that factor no level.
40 40 Flags such as pain carry no score and are absent here. *)
41 41 }
42 Removed: (** One subjective-feedback report, ready to render. Carries no
43 Removed: [Evidence.Feedback] variant and no timestamp type. *)
42 Added: (** One subjective-feedback report, ready to render. Carries no [Feedback]
43 Added: variant and no timestamp type. *)
44 44 end
45 45
46 46 module Routine = struct
lib/web/handlers_kit.ml
index aca2b64d..27a1639c 100644..100644
@@ -130,14 +130,14 @@
130 130 | `Incorrect_password -> "The current password is not correct."
131 131 | `Unknown -> "That account no longer exists."
132 132
133 Removed: let feedback_level : Evidence.Feedback.level -> string = function
134 Removed: | Evidence.Feedback.Worse_than_usual -> "worse than usual"
135 Removed: | Evidence.Feedback.As_usual -> "as usual"
136 Removed: | Evidence.Feedback.Better_than_usual -> "better than usual"
133 Added: let feedback_level : Feedback.level -> string = function
134 Added: | Feedback.Worse_than_usual -> "worse than usual"
135 Added: | Feedback.As_usual -> "as usual"
136 Added: | Feedback.Better_than_usual -> "better than usual"
137 137
138 Removed: let feedback_signal : Evidence.Feedback.signal -> string = function
139 Removed: | Evidence.Feedback.Motivation l -> "Motivation " ^ feedback_level l
140 Removed: | Evidence.Feedback.Difficulty l -> "Difficulty " ^ feedback_level l
138 Added: let feedback_signal : Feedback.signal -> string = function
139 Added: | Feedback.Motivation l -> "Motivation " ^ feedback_level l
140 Added: | Feedback.Difficulty l -> "Difficulty " ^ feedback_level l
141 141
142 142 let app_feedback_empty = "Enter feedback before submitting."
143 143 let username_changed = "Username changed."
lib/web/handlers_logbook.ml
index fbdb91a3..00c3fce1 100644..100644
@@ -61,9 +61,9 @@
61 61
62 62 let feedback_signals answers _fields =
63 63 let level = function
64 Removed: | "worse" -> Evidence.Feedback.Worse_than_usual
65 Removed: | "better" -> Evidence.Feedback.Better_than_usual
66 Removed: | _ -> Evidence.Feedback.As_usual
64 Added: | "worse" -> Feedback.Worse_than_usual
65 Added: | "better" -> Feedback.Better_than_usual
66 Added: | _ -> Feedback.As_usual
67 67 in
68 68 let leveled field make =
69 69 List.find_map
@@ -75,26 +75,26 @@
75 75 in
76 76 List.filter_map Fun.id
77 77 [
78 Removed: leveled "motivation" (fun l -> Evidence.Feedback.Motivation l);
79 Removed: leveled "difficulty" (fun l -> Evidence.Feedback.Difficulty l);
78 Added: leveled "motivation" (fun l -> Feedback.Motivation l);
79 Added: leveled "difficulty" (fun l -> Feedback.Difficulty l);
80 80 ]
81 81
82 82 let describe_signal = Present.feedback_signal
83 83 let factor_fields = [ "motivation"; "difficulty" ]
84 84
85 Removed: let factor_score field (report : Evidence.Feedback.t) =
85 Added: let factor_score field (report : Feedback.t) =
86 86 let score = function
87 Removed: | Evidence.Feedback.Worse_than_usual -> 1
87 Added: | Feedback.Worse_than_usual -> 1
88 88 | As_usual -> 2
89 89 | Better_than_usual -> 3
90 90 in
91 Removed: let of_signal (signal : Evidence.Feedback.signal) =
91 Added: let of_signal (signal : Feedback.signal) =
92 92 match (field, signal) with
93 93 | "motivation", Motivation l | "difficulty", Difficulty l ->
94 94 Some (score l)
95 95 | _ -> None
96 96 in
97 Removed: List.find_map of_signal (Evidence.Feedback.signals report)
97 Added: List.find_map of_signal (Feedback.signals report)
98 98
99 99 let entry_view log (record : Repository.record) : View_model.Logbook_entry.t =
100 100 let workout = record.Repository.workout in
@@ -114,13 +114,10 @@
114 114 progressed_exercises = Progress.workout_progress log workout;
115 115 }
116 116
117 Removed: let feedback_view (report : Evidence.Feedback.t) : View_model.Feedback.report
118 Removed: =
117 Added: let feedback_view (report : Feedback.t) : View_model.Feedback.report =
119 118 {
120 Removed: at_unix =
121 Removed: Recovery.timestamp_to_unix_seconds
122 Removed: (Evidence.Feedback.reported_at report);
123 Removed: signals = List.map describe_signal (Evidence.Feedback.signals report);
119 Added: at_unix = Recovery.timestamp_to_unix_seconds (Feedback.reported_at report);
120 Added: signals = List.map describe_signal (Feedback.signals report);
124 121 factor_scores =
125 122 List.map (fun f -> (f, factor_score f report)) factor_fields;
126 123 }
test/memory_repo.ml
index 377f8026..90615a71 100644..100644
@@ -5,7 +5,7 @@
5 5 mutable active : Repository.routine_id option;
6 6 mutable current : Evidence.Workout.t option;
7 7 mutable stored : Repository.record list; (* most recent first *)
8 Removed: mutable feedback : Evidence.Feedback.t list; (* most recent first *)
8 Added: mutable feedback : Feedback.t list; (* most recent first *)
9 9 mutable batches : Workout_import.batch list;
10 10 (* insertion order, newest first *)
11 11 mutable records : Repository.imported_record list; (* newest ended_at first *)
test/test_codec.ml
index 44804bfd..a46381ec 100644..100644
@@ -184,7 +184,7 @@
184 184 ( "relative feedback round-trips every level",
185 185 `Quick,
186 186 fun () ->
187 Removed: let open Evidence.Feedback in
187 Added: let open Feedback in
188 188 let report =
189 189 make ~reported_at:(at 100)
190 190 [ Motivation Better_than_usual; Difficulty Worse_than_usual ]
@@ -213,12 +213,10 @@
213 213 | Ok report ->
214 214 Alcotest.(check bool)
215 215 "legacy levels mapped" true
216 Removed: (Evidence.Feedback.signals report
216 Added: (Feedback.signals report
217 217 = [
218 Removed: Evidence.Feedback.Motivation
219 Removed: Evidence.Feedback.Worse_than_usual;
220 Removed: Evidence.Feedback.Difficulty
221 Removed: Evidence.Feedback.Better_than_usual;
218 Added: Feedback.Motivation Feedback.Worse_than_usual;
219 Added: Feedback.Difficulty Feedback.Better_than_usual;
222 220 ])
223 221 | Error e -> Alcotest.failf "decode failed: %a" Codec.pp_error e );
224 222 ]
test/test_evidence.ml
index 34075a97..867612a5 100644..100644
@@ -2,7 +2,6 @@
2 2
3 3 module Stimulus = Evidence.Stimulus
4 4 module Workout = Evidence.Workout
5 Removed: module Feedback = Evidence.Feedback
6 5 module Log = Evidence.Log
7 6 module Observation = Evidence.Observation
8 7
test/test_sqlite_repo.ml
index eb2d5698..e4d08101 100644..100644
@@ -292,10 +292,8 @@
292 292 (run
293 293 (S.record_feedback s id ~reported_at:(day 1)
294 294 [
295 Removed: Evidence.Feedback.Motivation
296 Removed: Evidence.Feedback.Better_than_usual;
297 Removed: Evidence.Feedback.Difficulty
298 Removed: Evidence.Feedback.As_usual;
295 Added: Feedback.Motivation Feedback.Better_than_usual;
296 Added: Feedback.Difficulty Feedback.As_usual;
299 297 ]))
300 298 in
301 299 id
@@ -306,18 +304,14 @@
306 304 let s = S.make ~repo in
307 305 let reports = run (S.feedback s t) in
308 306 Alcotest.(check int) "one feedback report" 1 (List.length reports);
309 Removed: let signals = Evidence.Feedback.signals (List.hd reports) in
307 Added: let signals = Feedback.signals (List.hd reports) in
310 308 Alcotest.(check int) "two signals" 2 (List.length signals);
311 309 Alcotest.(check bool)
312 310 "motivation signal preserved" true
313 Removed: (List.mem
314 Removed: (Evidence.Feedback.Motivation
315 Removed: Evidence.Feedback.Better_than_usual) signals);
311 Added: (List.mem (Feedback.Motivation Feedback.Better_than_usual) signals);
316 312 Alcotest.(check bool)
317 313 "difficulty signal preserved" true
318 Removed: (List.mem
319 Removed: (Evidence.Feedback.Difficulty Evidence.Feedback.As_usual)
320 Removed: signals)) );
314 Added: (List.mem (Feedback.Difficulty Feedback.As_usual) signals)) );
321 315 ( "application feedback survives a reconnect",
322 316 `Quick,
323 317 fun () ->
test/test_web.ml
index 48fa1ae6..e4af5950 100644..100644
@@ -781,14 +781,12 @@
781 781 in
782 782 Alcotest.(check int)
783 783 "one feedback report stored" 1 (List.length reports);
784 Removed: let signal_list = Evidence.Feedback.signals (List.hd reports) in
784 Added: let signal_list = Feedback.signals (List.hd reports) in
785 785 Alcotest.(check (list bool))
786 786 "only motivation stored" [ true ]
787 787 (List.map
788 788 (function
789 Removed: | Evidence.Feedback.Motivation
790 Removed: Evidence.Feedback.Better_than_usual ->
791 Removed: true
789 Added: | Feedback.Motivation Feedback.Better_than_usual -> true
792 790 | _ -> false)
793 791 signal_list) );
794 792 ( "skipping the entire feedback flow records nothing",
@@ -833,14 +831,12 @@
833 831 Lwt_main.run (Memory_repo.feedback repo trainee.Trainee.id)
834 832 in
835 833 Alcotest.(check int) "one report stored" 1 (List.length reports);
836 Removed: let signals = Evidence.Feedback.signals (List.hd reports) in
834 Added: let signals = Feedback.signals (List.hd reports) in
837 835 Alcotest.(check bool)
838 836 "the pre-back motivation answer persists" true
839 837 (List.exists
840 838 (function
841 Removed: | Evidence.Feedback.Motivation
842 Removed: Evidence.Feedback.Better_than_usual ->
843 Removed: true
839 Added: | Feedback.Motivation Feedback.Better_than_usual -> true
844 840 | _ -> false)
845 841 signals) );
846 842 ( "closing the feedback modal discards the flow",
@@ -1677,9 +1673,9 @@
1677 1673 Lwt_main.run (Memory_repo.feedback repo trainee.Trainee.id)
1678 1674 in
1679 1675 Alcotest.(check int) "one report stored" 1 (List.length reports);
1680 Removed: let signals = Evidence.Feedback.signals (List.hd reports) in
1676 Added: let signals = Feedback.signals (List.hd reports) in
1681 1677 let count p = List.length (List.filter p signals) in
1682 Removed: let open Evidence.Feedback in
1678 Added: let open Feedback in
1683 1679 Alcotest.(check int)
1684 1680 "one motivation signal" 1
1685 1681 (count (function Motivation _ -> true | _ -> false));