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.

Commit
0c47504067a71f282666b6b5fcdaa0dac4ccbc53
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
ARCHITECTURE.md
index ac9acef0..95732a69 100644..100644
@@ -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.