[OCaml] High Intensity Training Online
docs rewrite ARCHITECTURE for the HD1-sourced ontology
Describes what the code now is: the stimulus as the unit of work, failure as an invariant, recovery as a precondition, the logbook as the only evidence, and judgment confined to Progression. Records the epistemic layering and the table of which principle is enforced where, since there is deliberately no module of constants. Also records the tensions rather than hiding them: HD1's own 48h-versus-72h discrepancy, our departure in allowing per-exercise rep windows (including the argument against it), the dropped consolidation routine, and why extra volume and extension rarity are diagnostics rather than invariants.
ARCHITECTURE.md
@@ -1,119 +1,168 @@
1
1
# hito architecture
2
2
3
Removed:
A weightlifting tracker that encodes Mike Mentzer's Heavy Duty philosophy and enforces its invariants via the OCaml type system.
3
Added:
A weightlifting tracker that encodes Mike Mentzer's Heavy Duty in the type
4
Added:
system. This document describes the code as it stands, and is derived from
5
Added:
*Heavy Duty I* (HD1) as the primary source; `doc/` holds the text.
4
6
5
Removed:
## Layers
7
Added:
## What exists
6
8
7
Removed:
Three top-level libraries.
9
Added:
Mentzer argued bodybuilding had to be derived from principles rather than copied
10
Added:
from champions, so the domain is carved along his claims rather than along
11
Added:
convenient nouns.
8
12
9
Removed:
```
10
Removed:
hito.web Eliom application (pages, services) [stubs]
11
Removed:
|
12
Removed:
hito.app Repository port, Service functor, adapters [stubs]
13
Removed:
|
14
Removed:
hito.core pure domain — no framework, DB, or serialization
15
Removed:
```
13
Added:
**The stimulus is the unit of work** — one drive to muscular failure. HD1
14
Added:
prescribes one set per exercise, so there is no set count to record, and no "set
15
Added:
group" wrapping anything. How a drive was delivered is a property of the stimulus.
16
16
17
Removed:
`hito.core` is split into four sub-libraries with enforced, acyclic
18
Removed:
dependencies:
17
Added:
**Reaching failure is an invariant, not data.** A recorded movement went to
18
Added:
failure by construction; that is what separates a stimulus from mere exercise.
19
Added:
What varies is load, the reps it happened to yield, and whether anything carried
20
Added:
the effort past failure.
19
21
22
Added:
**Recovery is a precondition.** Training before the body has replenished its
23
Added:
reserves is HD1's primary error, and its effects are systemic rather than local.
24
Added:
Beginning a workout therefore demands an unforgeable clearance.
25
Added:
26
Added:
**The logbook is the only source of evidence.** Progress is knowable only from
27
Added:
records, so history is never edited to suit the theory.
28
Added:
29
Added:
**Judgment is one module's job.** Prescriptions state what to do, the logbook
30
Added:
states what happened, and `Progression` alone decides what that means.
31
Added:
32
Added:
## Layers
33
Added:
34
Added:
One library, `hito.core`, with eleven modules. Dependencies point downward.
35
Added:
20
36
```
21
Removed:
vocabulary ← assessment ← prescription ← logbook
22
Removed:
^______________|____________|___________|
23
Removed:
(everything depends on vocabulary)
37
Added:
vocabulary Units · Muscle · Exercise
38
Added:
normative Prescription · Workout_prescription · Routine
39
Added:
factual Stimulus · Entry · Logbook
40
Added:
inferential Progression
41
Added:
Recovery straddles: it measures fact, and issues a
42
Added:
normative clearance
24
43
```
25
44
26
Removed:
- **vocabulary** — the nouns. `Units`, `Exercise`, `Set`.
27
Removed:
- **assessment** — judging performance and time. `Progression`, `Recovery`.
28
Removed:
- **prescription** — the plan side. `Prescription`, `Set_group_prescription`,
29
Removed:
`Workout_prescription`, `Routine`.
30
Removed:
- **logbook** — the record side. `Set_group`, `Logbook`.
45
Added:
The split is epistemic — what a module *claims* — expressed as layering and
46
Added:
documentation rather than as sub-libraries or a module of constants. There is no
47
Added:
`Principle` module: a module cohering around "things that are true" is a
48
Added:
constants bag, and each principle is instead enforced where it bites.
31
49
32
Removed:
`Set` lives in vocabulary (not logbook) because `Progression` reads
33
Removed:
`Set.Working.performance`; placing it in logbook would cycle assessment against
34
Removed:
logbook.
50
Added:
| Principle | Enforced at |
51
Added:
|---|---|
52
Added:
| 6-12 stimulus window | `Prescription.rep_limits` |
53
Added:
| one drive to failure per slot | `Workout_prescription` construction |
54
Added:
| isolation into compound, sharing a muscle | `Exercise.may_pre_exhaust` |
55
Added:
| every other day, then two days off | `Routine.recovery_after` |
56
Added:
| load rises at twelve reps, by 10-20% | `Progression.judge_load` |
57
Added:
| never add work on a stall | `Progression.remedy` |
35
58
59
Added:
`lib/app` and `lib/web` are parked (`dune.disabled`) — their stubs predate this
60
Added:
ontology.
61
Added:
36
62
## Modules
37
63
38
Removed:
### vocabulary
64
Added:
### Vocabulary
39
65
40
Removed:
- **Units** — `Weight` (kg, ≥0), `Reps` (>0), `Rep_range` (min≤max). Abstract,
41
Removed:
constructed only through validating smart constructors.
42
Removed:
- **Exercise** — the curated catalog. Exercises exist only in `catalog`;
43
Removed:
substitutions are limited to each exercise's author-specified whitelist.
44
Removed:
- **Set** — one bout. `Warm_up` and `Working` are distinct types: a working set
45
Removed:
always reaches failure, recording only *how* (`Positive_failure` or
46
Removed:
`Beyond_failure` via forced reps / negatives / rest-pause / static hold).
47
Removed:
Intensity is categorical, never a number.
66
Added:
- **Units** — `Weight` (kg, zero for bodyweight movements), `Reps`, `Rep_range`.
67
Added:
Abstract, reachable only through validating constructors.
68
Added:
- **Muscle** — the thirteen targets HD1 names. Deliberately minimal: it exists
69
Added:
only so a pre-exhaust pairing can be checked.
70
Added:
- **Exercise** — the curated catalog, each movement carrying a mechanic
71
Added:
(isolation or compound) and the muscles it works. Substitutions come from HD1's
72
Added:
own "or" lists, grouped so symmetry is structural.
48
73
49
Removed:
### assessment
74
Added:
### Normative — the plan
50
75
51
Removed:
- **Progression** — the only module that judges performance against a plan.
52
Removed:
`Progressing | Stalled`; classifies a performance against a rep band
53
Removed:
(`Below/In/Above_range`); prescribes the next target (add reps within the
54
Removed:
band, then add load); tracks volume as a diagnostic.
55
Removed:
- **Recovery** — time. `timestamp`, `duration`, `elapsed`, and a `readiness`
56
Removed:
reading (elapsed vs. a recommended window). Purely informational — it gates
57
Removed:
nothing.
76
Added:
- **Prescription** — one prescribed stimulus: a delivery, plus the rep window
77
Added:
calibrating its load. Delivery is `Single` or `Pre_exhaust`, and nothing else:
78
Added:
in HD1 "superset" *means* pre-exhaustion.
79
Added:
- **Workout_prescription** — an ordered sequence of prescribed stimuli, such as
80
Added:
Day 1. Volume needs no representation, being the length of that sequence.
81
Added:
- **Routine** — the cycle of workouts, and how long to rest between them.
82
Added:
`workout_after` advances by identity, so rotation follows from what was last
83
Added:
performed. Ships HD1's Ideal Routine.
58
84
59
Removed:
### prescription (the plan — static, no history)
85
Added:
### Factual — the record
60
86
61
Removed:
- **Prescription** — one exercise's plan: movement, target rep band, permitted
62
Removed:
substitutes.
63
Removed:
- **Set_group_prescription** — how prescriptions are grouped:
64
Removed:
`Straight | Superset | Pre_exhaust`.
65
Removed:
- **Workout_prescription** — one workout (e.g. "Workout A"): an ordered list of
66
Removed:
set-group prescriptions, with an `id`.
67
Removed:
- **Routine** — a sequence of prescribed workouts cycled through over time.
68
Removed:
`workout_after` gives the next workout in the cycle. Ships the Ideal and
69
Removed:
Consolidation presets.
87
Added:
- **Stimulus** — one drive to failure: how it was delivered, what each movement
88
Added:
lifted, and whether extensions carried it past failure. Warm-ups sit alongside
89
Added:
and carry no outcome, so a warm-up cannot reach failure by type.
90
Added:
- **Entry** — a workout performed against its prescription. Starting one requires
91
Added:
a clearance; adding a stimulus requires that the prescription actually calls
92
Added:
for it.
93
Added:
- **Logbook** — every entry, plus the questions history answers: what was
94
Added:
performed last, how long since the last finished workout, and what a movement
95
Added:
has done over time. Evidence is dated, because a stall is defined by two weeks
96
Added:
of nothing.
70
97
71
Removed:
### logbook (the record — what happened)
98
Added:
### Recovery
72
99
73
Removed:
- **Set_group** — the performed counterpart to `Set_group_prescription`:
74
Removed:
`straight` / `superset` / `pre_exhaust` holding actual `Set.Working.t`s.
75
Removed:
- **Logbook** — the training diary. `Entry` wraps the `Workout_prescription` it
76
Removed:
was performed against plus start/end timestamps and logged set groups; it
77
Removed:
validates each logged set against the prescription, and reports guidance,
78
Removed:
unperformed exercises, and volume. The `Logbook` itself yields per-exercise
79
Removed:
`evidence`, the `last_prescription` (for rotation), and a `readiness` reading.
100
Added:
Timestamps, durations, elapsed rest, a readiness reading — and `clearance`, an
101
Added:
abstract permission to train. A clearance is either earned by having recovered,
102
Added:
or taken through `override`, which records how long you had rested and why you
103
Added:
went ahead. The override is not an escape hatch but evidence: it is what lets a
104
Added:
stall later be attributed to training under-recovered.
80
105
81
Removed:
### hito.app (stubs)
106
Added:
### Inferential
82
107
83
Removed:
- **Repository** — persistence port (module type). Assigns identity
84
Removed:
(`routine_id`, `workout_id`); stores logbook entries as records.
85
Removed:
- **Memory_repo** — in-memory adapter, seeded with the presets.
86
Removed:
- **Service** — orchestration over a repository: prescribe the next workout,
87
Removed:
start logging, log a group, finish and persist, read history.
108
Added:
- **Progression** — whether the record shows progress, and what follows. Progress
109
Added:
is an increase in reps, weight or both, one rep being significant. A stall is
110
Added:
progress ceasing entirely for two weeks, and its single remedy subtracts: a
111
Added:
week off, one fewer stimulus per workout, an extra rest day. There is no
112
Added:
additive remedy, structurally. Diagnostics report habits HD1 names as causes of
113
Added:
overtraining.
88
114
89
Removed:
### hito.web (stubs)
115
Added:
## The cycle
90
116
91
Removed:
- **App** / **Pages** / **Services** — the Eliom application: choose a routine,
92
Removed:
log a workout, view history.
117
Added:
```mermaid
118
Added:
graph LR
119
Added:
R[Routine] -->|workout_after| WP[Workout_prescription]
120
Added:
WP -->|start, needs clearance| E[Entry]
121
Added:
S[Stimulus] --> E
122
Added:
E --> L[Logbook]
123
Added:
L -->|dated evidence| P[Progression]
124
Added:
L -->|elapsed| RC[Recovery]
125
Added:
RC -->|clearance| E
126
Added:
P -.->|remedy| R
127
Added:
```
93
128
94
Removed:
## Data flow
129
Added:
Plan and record are distinct types with a one-way transition. Prescriptions never
130
Added:
learn what was performed; the logbook never interprets.
95
131
96
Removed:
```
97
Removed:
Routine ──workout_after──▶ Workout_prescription
98
Removed:
│ start
99
Removed:
▼
100
Removed:
Logbook.Entry ──add_group──▶ (validated against the prescription)
101
Removed:
│ finish
102
Removed:
▼
103
Removed:
Logbook ──evidence──▶ Progression (guidance, next target)
104
Removed:
└──elapsed────▶ Recovery (readiness)
105
Removed:
```
132
Added:
## Deviations and tensions
106
133
107
Removed:
Plan and record are distinct types with a one-way transition: a
108
Removed:
`Workout_prescription` is instantiated into a `Logbook.Entry` when logging
109
Removed:
begins. Prescriptions never know what was performed; the logbook never
110
Removed:
interprets — judging is `Progression`'s job alone.
134
Added:
Recorded rather than resolved, since the source does not settle them.
111
135
112
Removed:
## Guiding invariants
136
Added:
**48h against 72h.** Chapter 3 says up to 72 hours of rest, and in some cases
137
Added:
more, is needed for growth. The Ideal Routine prescribes training every other
138
Added:
day. Mentzer does not reconcile these. We encode what the routine says — 48h
139
Added:
within a cycle, 72h after it — and note the discrepancy here.
113
140
114
Removed:
- Illegal states are unrepresentable where practical; otherwise a smart
115
Removed:
constructor returns a module-specific `result` error.
116
Removed:
- One working set per exercise is the Heavy Duty norm; deviation is structural,
117
Removed:
not a silent flag.
118
Removed:
- Recovery is elapsed time read off the logbook, judged advisorily — never a
119
Removed:
gate.
141
Added:
**Per-exercise rep windows.** HD1 gives one guideline, 6-10, for every listed
142
Added:
exercise. We allow a prescription to name its own window, bounded to lie within
143
Added:
6-12, on the argument that leg work may warrant a different range. This is a
144
Added:
deliberate departure. Note that Mentzer's own rationale for the upper bound —
145
Added:
cardiorespiratory failure arriving before muscular failure — cuts against higher
146
Added:
reps for large compounds rather than for them.
147
Added:
148
Added:
**No consolidation routine.** HD2 material, and we have no source for it.
149
Added:
150
Added:
**Extra volume is recordable.** HD1 forbids it in the strongest terms, but a log
151
Added:
that refuses to state what happened is worse than one that records an error. The
152
Added:
constraint lives on the prescription side, which cannot prescribe extra work;
153
Added:
performing extra shows as more stimuli than slots.
154
Added:
155
Added:
**Extension rarity is a diagnostic, not an invariant.** Same reason: HD1 says
156
Added:
never to extend every exercise of a workout, but if you did, the record must say
157
Added:
so. Invariants belong on plans, which you author; not on history, which you
158
Added:
observe.
159
Added:
160
Added:
**Deadlifts substitute for hyperextensions** across mechanics, because HD1 offers
161
Added:
them as alternatives despite one being an isolation and the other a compound.
162
Added:
163
Added:
## Deferred
164
Added:
165
Added:
Equipment granularity, so a suggested load can be one a bar actually takes; a
166
Added:
trainee layer, carrying individual recovery ability, spotter availability, and
167
Added:
the way recovery needs outgrow strength; HD2 consolidation once sourced; and the
168
Added:
app and web tiers.