(** Subjective self-reports at a point in time: what the trainee said, not what the body did. HD1 grounds two of them. HD1 gauges recovery by time and by effect, not by a wider battery of wellness proxies. *) type level = | Worse_than_usual | As_usual | Better_than_usual (** A self-report relative to the trainee's usual baseline, not an absolute score. HD1 frames both signals this way — Difficulty is "the weights feel much heavier than usual". Three values resist the false precision of a finer scale, and match HD1's refusal of a finer measurement scale. [Worse_than_usual] is the concerning direction for both signals. *) val pp_level : Format.formatter -> level -> unit type signal = | Motivation of level | Difficulty of level (** The only self-reports HD1 grounds. Motivation is HD1 chapter 6, and a halt in motivation is a recognized overtraining symptom ("with those who chronically overtrain, such a disinclination is easy to understand"). Difficulty is HD1's "the weights feel much heavier than usual" — a depletion symptom. HD1 gauges recovery by time and by effect (a stall or decompensation), not by a wider battery of wellness proxies. This module models none of the other proxies. *) type t type error = Duplicate_signal of signal exception Invalid of error val make : reported_at:Recovery.timestamp -> signal list -> t (** Raises [Invalid] when feedback repeats a signal category. *) val reported_at : t -> Recovery.timestamp val signals : t -> signal list