docs record the app and web tiers, and correct stale steering

ARCHITECTURE no longer describes app and web as parked. Adds how to run the server, the route table, and why the paths are flat; records that recovery policy lives in Service so a second client cannot adopt looser rules, and that both storage and the in-progress slot are single-user and must become per-trainee before authentication exists. Two lines in the domain steering were not merely stale but standing instructions to rebuild what the HD1 rebuild removed. Steering is always in context and normative, so a wrong line there is worse than a wrong line in a document: - "once the band is exceeded, add load and reset to its bottom" described a rule the source contradicts. The trigger is twelve reps, not exceeding the band — a 6-10 band is not breached at eleven — and the increase is a 10-20% window. Reps are an outcome, so the band only calibrates load. - "Anything prescribed is derived from logged evidence and carries that evidence plus the status computed from it" described the 'a prescribed record, deleted in the rebuild. Replaced with what the code now upholds: the logbook records and never interprets, invariants belong on plans rather than on history, and no remedy may add volume or frequency. Also notes the one knowing gap between form and model: the log form offers a single extension where Stimulus permits a stack.

Commit
c2c42176fe21c86bc7d1e9679cab9bf670a129fa
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
.kiro/steering/domain.md
index 9cab54ec..6ba58926 100644..100644
@@ -15,8 +15,12 @@
15 15 - **Volume beyond the minimum is harmful.** One working set per exercise is
16 16 nominal. Rising volume is a diagnostic warning, never an achievement or a
17 17 progress target.
18 Removed: - **Progressive overload is the progress signal.** Add reps within the
19 Removed: prescribed band; once the band is exceeded, add load and reset to its bottom.
18 Added: - **Progressive overload is the progress signal.** Progress is an increase in
19 Added: reps, weight or both; one extra rep counts. Reps are an *outcome*, never a
20 Added: target — a set ends at failure, not at a number, so the prescribed band only
21 Added: calibrates load. Raise the load once twelve reps are reached, by 10-20%, so
22 Added: failure returns inside the band. Note the slack: a 6-10 band is not breached
23 Added: at eleven.
20 24 - **Brief, infrequent, intense.** Shorter sessions at equal or better overload
21 25 are favourable.
22 26 - **Focus over novelty.** Exercises come from a curated catalog; substitutions
@@ -30,5 +34,9 @@
30 34 never *silent*: require an explicit acknowledgement and retain it.
31 35 - Keep plan and record distinct: prescription/routine vs logged workout;
32 36 prescription vs progression (plan vs observation).
33 Removed: - Anything prescribed is derived from logged evidence and carries that evidence
34 Removed: plus the status computed from it.
37 Added: - The logbook records; it never interprets. Judgement belongs to one module.
38 Added: Invariants belong on plans, which are authored, not on history, which is
39 Added: observed — a log that refuses to state what happened is worse than one
40 Added: recording an error.
41 Added: - On a stall the answer is never more work. No remedy may add volume or
42 Added: frequency.
ARCHITECTURE.md
index 6cc40878..632d2619 100644..100644
@@ -60,9 +60,17 @@
60 60 a field, and the last two are the shape of a return type. That is the intended
61 61 bias — a principle enforced by a type cannot be forgotten at a call site.
62 62
63 Removed: `lib/app` and `lib/web` are parked (`dune.disabled`) — their stubs predate this
64 Removed: ontology.
63 Added: Above the core sit two more libraries, dependencies pointing inward only:
65 64
65 Added: - **`hito.app`** — `Repository` (a port, no database), `Memory_repo`, and
66 Added: `Service`. Identity is assigned here, since the core carries none, and so is
67 Added: recovery policy: `Service` is the only thing that decides how a
68 Added: `Recovery.clearance` is obtained, so a second client cannot quietly adopt
69 Added: looser rules than the first.
70 Added: - **`hito.web`** — `Routes`, `Pages`, `Services`. The only place Eliom appears.
71 Added: Server-rendered: no client-side OCaml, no ppx, no js_of_ocaml. Wall-clock time
72 Added: enters here, never in the core.
73 Added:
66 74 ## Modules
67 75
68 76 ### Vocabulary
@@ -142,6 +150,40 @@
142 150 a remedy, but no code applies it to a routine. Acting on it belongs to a tier
143 151 that does not exist yet.
144 152
153 Added: ## Running it
154 Added:
155 Added: ```
156 Added: dune build && ./_build/default/bin/main.exe # http://localhost:8080/
157 Added: ```
158 Added:
159 Added: `bin/main.ml` starts ocsigenserver programmatically — `Eliom.run` yields an
160 Added: `Ocsigen_server.instruction`, so there is no XML configuration to keep in sync
161 Added: and no `.cmxs` loaded at runtime. The socket binds **loopback only**, and there
162 Added: is **no authentication**: anything beyond local dogfooding needs auth first.
163 Added:
164 Added: Storage is in-memory, so a restart wipes the log. The workout in progress is a
165 Added: single slot in `Service.t`, not a session reference — it survives a closed tab,
166 Added: and is single-user by construction. Both must become per-trainee before auth.
167 Added:
168 Added: | Route | Method | Purpose |
169 Added: |---|---|---|
170 Added: | `/` | GET | Choose a routine, or resume one in progress |
171 Added: | `/begin` | POST | Start the next workout, or refuse and show the gate |
172 Added: | `/log` | GET | The workout in progress |
173 Added: | `/log-single` | POST | Record one movement driven to failure |
174 Added: | `/log-pair` | POST | Record an isolation carried into a compound |
175 Added: | `/finish` | POST | Complete and persist |
176 Added: | `/history` | GET | What has been performed |
177 Added:
178 Added: Paths are flat because Eliom treats a path as either a page or a directory: a
179 Added: page at `/log` cannot coexist with `/log/single`.
180 Added:
181 Added: The refusal at `/begin` is two steps, not one click. It reports how much of the
182 Added: recommended rest remains and starts nothing; training anyway requires stating a
183 Added: reason, which is kept with the entry and reaches `Progression.diagnose`. That is
184 Added: the clearance invariant made visible — the one place the UI has to express a core
185 Added: rule rather than merely display data.
186 Added:
145 187 ## Tests
146 188
147 189 One Alcotest suite per module, `test/test_<module>.ml`, each exposing a `suite`
@@ -178,9 +220,15 @@
178 220 **Deadlifts substitute for hyperextensions** across mechanics, because HD1 offers
179 221 them as alternatives despite one being an isolation and the other a compound.
180 222
223 Added: **The log form offers one extension, not a stack.** `Stimulus` permits forced
224 Added: reps *then* negatives, as HD1 describes; the web form currently offers a single
225 Added: choice per stimulus. A limitation of the form, not the model.
226 Added:
181 227 ## Deferred
182 228
183 Removed: Equipment granularity, so a suggested load can be one a bar actually takes; a
184 Removed: trainee layer, carrying individual recovery ability, spotter availability, and
185 Removed: the way recovery needs outgrow strength; HD2 consolidation once sourced; and the
186 Removed: app and web tiers.
229 Added: Authentication, and with it per-trainee storage and workout state — required
230 Added: before this runs anywhere but localhost. Durable storage behind the same
231 Added: `Repository` port. Equipment granularity, so a suggested load is one a bar
232 Added: actually takes. A trainee layer carrying individual recovery ability, spotter
233 Added: availability, and the way recovery needs outgrow strength. HD2 consolidation once
234 Added: sourced. A native client, which would sit on `hito.app` beside the web tier.