[OCaml] High Intensity Training Online
docs Realign steering and README with the repository
Rewrite the steering files and the README in ASD-STE100 Simplified Technical English, and correct the statements that no longer match the code. - Name doc/hd1.md as the doctrine source. - Describe the real dependencies of hito.import and hito.app. - Make scripts/ci.sh and the pre-push hook the verification owner, so that agents do not repeat checks that automation already did. - Describe what the deployment hook verifies. - Replace the stale ogit watch-process example with hito. ARCHITECTURE.org is not yet realigned.
Changed files
.kiro/skills/doctrine-check/SKILL.md
@@ -17,10 +17,10 @@
17
17
18
18
The doctrine lives in two places, in this order of authority:
19
19
20
Removed:
1. `doc/Mike_Mentzer_Heavy_Duty_I.md` (HD1) — the primary source. It is
21
Removed:
copyrighted, gitignored, and never committed. Read it to cite exact wording.
22
Removed:
2. `.kiro/steering/domain.md` — the distilled, binding principles. Use it when
23
Removed:
HD1 is not present.
20
Added:
1. `doc/hd1.md` (HD1) is the primary source. It is copyrighted. Git ignores
21
Added:
it. Never commit it. Read it to quote the exact words.
22
Added:
2. `.kiro/steering/domain.md` contains the binding principles in short form.
23
Added:
Use it when HD1 is not available.
24
24
25
25
Cite HD1 by section name. The sections are:
26
26
.kiro/steering/domain.md
@@ -2,69 +2,77 @@
2
2
3
3
hito is a Heavy Duty training tracker.
4
4
5
Removed:
- Source of doctrine: `doc/Mike_Mentzer_Heavy_Duty_I.md` (HD1). You must
6
Removed:
justify every domain decision against it.
7
Removed:
- It is copyrighted local reference material, gitignored, and never committed.
8
Removed:
- On conflict between a design choice and the doctrine:
9
Removed:
1. The doctrine wins, or
10
Removed:
2. The conflict is raised explicitly.
5
Added:
- The source of doctrine is `doc/hd1.md` (HD1). `doc/hd1.docx` is the original
6
Added:
file. Justify each domain decision against HD1.
7
Added:
- HD1 is copyrighted local reference material. Git ignores `doc/`. Never
8
Added:
commit it.
9
Added:
- If a design choice and the doctrine do not agree, one of these outcomes
10
Added:
applies:
11
Added:
1. The doctrine wins.
12
Added:
2. You tell the user about the conflict explicitly.
11
13
12
14
## Principles that bind the model
13
15
14
16
- **Intensity is categorical, not scalar.**
15
Removed:
- You take a working set to momentary muscular failure. That *is* its
16
Removed:
definition (HD1, "The Intensity Factor": the only accurate measures are 0%
17
Removed:
at rest and 100% at failure).
18
Removed:
- Going further is qualitative — `Beyond_failure`: forced reps, negatives,
19
Removed:
static hold. Each is a count (reps, or seconds held). Rest-pause is not in
20
Removed:
HD1 and is not modeled.
21
Removed:
- Never introduce a numeric "intensity score".
22
Removed:
- **Recovery produces growth. The gym only stimulates it.**
23
Removed:
- Stimulation is immediate. Production is not (HD1, "The Economics of Growth
24
Removed:
and Recovery": recovery precedes growth).
25
Removed:
- Recovery is systemic and time-based — any hard workout gates the next one.
26
Removed:
- **Volume beyond the minimum is harmful.**
27
Removed:
- One working set per exercise is nominal. Three sets per muscle is the ceiling.
28
Removed:
A prescription that exceeds it is unrepresentable — `Prescription.Workout.make`
29
Removed:
refuses it.
30
Removed:
- The net negative effect of each extra set increases geometrically.
31
Removed:
- Rising volume is a diagnostic warning — never an achievement or a progress
32
Removed:
target.
17
Added:
- A working set continues to momentary muscular failure. This is the
18
Added:
definition of a working set (HD1, "The Intensity Factor": the only accurate
19
Added:
measures are 0% at rest and 100% at failure).
20
Added:
- Work past failure is qualitative. The model calls it `Beyond_failure`:
21
Added:
forced reps, negatives, or a static hold. Each one is a count (reps, or
22
Added:
seconds held). HD1 does not contain rest-pause, so the model does not
23
Added:
contain it.
24
Added:
- Never add a numeric "intensity score".
25
Added:
- **Recovery produces growth. The gym only stimulates growth.**
26
Added:
- Stimulation is immediate. Production is not immediate (HD1, "The Economics
27
Added:
of Growth and Recovery": recovery comes before growth).
28
Added:
- Recovery is systemic and depends on time. Each hard workout gates the next
29
Added:
workout.
30
Added:
- **Volume above the minimum is harmful.**
31
Added:
- One working set for each exercise is nominal. Three sets for each muscle
32
Added:
is the maximum. The model cannot represent a prescription that is more
33
Added:
than the maximum. `Prescription.Workout.make` refuses it.
34
Added:
- The negative effect of each extra set increases geometrically.
35
Added:
- An increase in volume is a diagnostic warning. It is never an achievement
36
Added:
or a progress target.
33
37
- **Progressive overload is the progress signal.**
34
Removed:
- Progress is an increase in reps, weight, or both. One extra rep counts.
35
Removed:
- Reps are an *outcome*, never a target — a set ends at failure, not at a
36
Removed:
number. The prescribed band only calibrates load.
37
Removed:
- Raise the load once twelve reps are reached, by 10-20%, so failure returns
38
Removed:
inside the band.
39
Removed:
- Note the slack: a 6-10 band is not breached at eleven.
38
Added:
- Progress is an increase in reps, in weight, or in both. One extra rep is
39
Added:
progress.
40
Added:
- Reps are an outcome, never a target. A set stops at failure, not at a
41
Added:
number. The prescribed band only calibrates the load.
42
Added:
- When the trainee gets twelve reps, increase the load by 10 to 20 percent.
43
Added:
Failure then occurs in the band again.
44
Added:
- The trigger is twelve reps for all bands. Eleven reps in a 6 to 10 band do
45
Added:
not trigger an increase.
40
46
- **Brief, infrequent, intense.**
41
Removed:
- Shorter sessions at equal or better overload are favourable.
47
Added:
- A shorter session with equal or better overload is better.
42
48
- **Focus over novelty.**
43
49
- Exercises come from a curated catalog.
44
Removed:
- Author-specified allowlists limit substitutions. A routine may only
45
Removed:
narrow them.
50
Added:
- Allowlists from the author limit substitutions. A routine can only make an
51
Added:
allowlist smaller.
46
52
47
53
## Encoding rules
48
54
49
Removed:
- Prefer making an illegal training state unrepresentable over validating it at
50
Removed:
runtime.
51
Removed:
- Deviations from doctrine (training early, extra volume) must be *possible* but
52
Removed:
never *silent*:
55
Added:
- Make an illegal training state impossible to represent. Prefer this to a
56
Added:
runtime check.
57
Added:
- A deviation from doctrine (early training, extra volume) must be possible,
58
Added:
but never silent:
53
59
- Require an explicit acknowledgement.
54
Removed:
- Retain that acknowledgement.
55
Removed:
- Keep plan and record distinct:
56
Removed:
- Prescription/routine vs logged workout.
57
Removed:
- Prescription vs progression (plan vs observation).
60
Added:
- Keep that acknowledgement.
61
Added:
- Keep the plan and the record separate:
62
Added:
- A prescription or routine is different from a logged workout.
63
Added:
- A prescription is different from a progression (plan against
64
Added:
observation).
58
65
- The logbook records. It never interprets.
59
Removed:
- Judgement belongs to one module.
60
Removed:
- Invariants belong on plans, which are authored — not on history, which is
61
Removed:
observed.
62
Removed:
- A log that refuses to state what happened is worse than one recording an
63
Removed:
error.
64
Removed:
- On a stall, the answer is never more work.
65
Removed:
- HD1 names two failure states: a *stall* (progress halts, strength holds)
66
Removed:
and *decompensation* (strength is lost). Both get the same corrective.
67
Removed:
- No remedy may add volume or frequency.
68
Removed:
- Doctrinal remedy (HD1, "Regulating Volume and Frequency"): after two weeks
69
Removed:
of no progress, take a week off, then *reduce* volume and frequency —
70
Removed:
drop sets and add rest days.
66
Added:
- One module owns all judgement.
67
Added:
- Invariants apply to plans, which are authored. They do not apply to
68
Added:
history, which is observed.
69
Added:
- A log that refuses to record what occurred is worse than a log that
70
Added:
records an error.
71
Added:
- When progress stops, the answer is never more work.
72
Added:
- HD1 names two failure states. In a *stall*, progress stops and strength
73
Added:
stays the same. In *decompensation*, strength decreases. Both get the same
74
Added:
correction.
75
Added:
- No remedy can add volume or frequency.
76
Added:
- The doctrinal remedy (HD1, "Regulating Volume and Frequency"): after two
77
Added:
weeks without progress, rest for one week. Then *decrease* volume and
78
Added:
frequency. Remove sets and add rest days.
.kiro/steering/ocaml.md
@@ -2,63 +2,74 @@
2
2
3
3
## Source of truth
4
4
5
Removed:
- `.mli` files are the specification and outrank tests.
6
Removed:
- If an interface and a test disagree, fix the test.
7
Removed:
- Changing an interface is a deliberate design decision. Raise it. Do not let
8
Removed:
the change drift in unannounced.
5
Added:
- The `.mli` files are the specification. They have a higher authority than
6
Added:
the tests.
7
Added:
- If an interface and a test do not agree, correct the test.
8
Added:
- A change to an interface is a design decision. Tell the user about it. Do
9
Added:
not change an interface without an announcement.
9
10
10
11
## Style
11
12
12
Removed:
- Modern, idiomatic OCaml. Favour the principle of least surprise: a reader
13
Removed:
should not need to learn a local idiom to follow the code.
14
Removed:
- Prefer readable, shallow code. A flat sequence a reader can follow top to
15
Removed:
bottom beats a deeply nested tower of `match` arms.
16
Removed:
- Reach for `let*` when it flattens nested cases — chained `result` or
17
Removed:
`result Lwt.t` plumbing where each step short-circuits on error. Used this
18
Removed:
way, a bind improves flow and cuts indentation.
19
Removed:
- A single `match` is clearer than a monad. Do not reach for one reflexively.
20
Removed:
- Two or three cascading `match ... with Error _ -> ... | Ok x -> ...`
21
Removed:
steps are the signal to change to `let*`.
22
Removed:
- Abstract types with smart constructors for anything carrying an invariant.
23
Removed:
- Use `result` for expected, recoverable failure.
24
Removed:
- This includes converting untrusted external data and domain feedback a caller
25
Removed:
can present or recover from.
26
Removed:
- Each module defines its own errors; no shared catch-all error type or
27
Removed:
`string` errors.
28
Removed:
- Raise a module-specific exception for a violated authored-plan precondition
29
Removed:
after validation.
30
Removed:
- Do not use exceptions for normal domain outcomes or recorded deviations.
31
Removed:
- Prefer closed variants — they keep `match` exhaustiveness complete.
32
Removed:
- Total functions where practical; make partiality visible in the type.
13
Added:
- Write modern, idiomatic OCaml. Follow the principle of least surprise. A
14
Added:
reader must not have to learn a local idiom to follow the code.
15
Added:
- Prefer shallow code that is easy to read. A flat sequence that a reader can
16
Added:
follow from top to bottom is better than deeply nested `match` arms.
17
Added:
- Use `let*` when it removes nested cases. A good example is a chain of
18
Added:
`result` or `result Lwt.t` steps where each step stops on an error.
19
Added:
- A single `match` is clearer than a monad. Do not use a monad by habit.
20
Added:
- Two or three cascading `match ... with Error _ -> ... | Ok x -> ...` steps
21
Added:
are the signal to change to `let*`.
22
Added:
- Use abstract types with smart constructors for each value that has an
23
Added:
invariant.
24
Added:
- Use `result` for an expected failure that a caller can recover from.
25
Added:
- This includes the conversion of untrusted external data and domain
26
Added:
feedback that a caller can show or recover from.
27
Added:
- Each module defines its own errors. Do not use a shared catch-all error
28
Added:
type or `string` errors.
29
Added:
- Raise a module-specific exception when validation finds a violated
30
Added:
precondition of an authored plan.
31
Added:
- Do not use exceptions for normal domain outcomes or for recorded
32
Added:
deviations.
33
Added:
- Prefer closed variants. They keep the exhaustiveness check of `match`
34
Added:
complete.
35
Added:
- Write total functions where possible. If a function is partial, show this in
36
Added:
its type.
33
37
34
38
## Layering
35
39
36
Removed:
Six libraries, dependencies pointing inward only. The build graph enforces the
37
Removed:
rule: a library cannot name what it does not link.
40
Added:
The project has six libraries. All dependencies point inward. The build graph
41
Added:
enforces this rule: a library cannot name a library that it does not link.
38
42
39
Removed:
- `hito.core` — pure domain. No framework, database, serialization, or Lwt
40
Removed:
dependency. Ever.
41
Removed:
- `hito.app` — `Repository` and `Password_hash` ports, `Service`, `Catalog`,
42
Removed:
`Workout_import`. Depends on `hito.core` and `lwt` only. Knows nothing of
43
Removed:
Dream, Caqti, or any adapter.
44
Removed:
- `hito.import` — adapters for third-party exports (`Hevy_csv`). Depends on
45
Removed:
`hito.app` and the parser it needs. No web framework.
46
Removed:
- `hito.persistence` — adapters that implement the ports: `Sqlite_repo`,
47
Removed:
`Bcrypt_hash`, `Codec`, `Migrations`. The only place SQL appears.
48
Removed:
- `hito.presenter` — view models, routes, pages. Depends on Dream and
49
Removed:
dream-html only. It cannot name a core entity, a service, or an adapter.
50
Removed:
- `hito.web` — Dream controllers. Maps entities to view models, owns all
51
Removed:
user-facing phrasing (`Present`), and never reaches an adapter directly.
43
Added:
- `hito.core` is the pure domain. It has no library dependencies: no
44
Added:
framework, no database, no serialization, and no Lwt.
45
Added:
- `hito.app` contains the ports `Repository`, `Password_hash`, and
46
Added:
`Importer`, plus `Trainee`, `Service`, `Catalog`, and `Workout_import`. It
47
Added:
depends on `hito.core` and `lwt` only. It does not know about Dream, Caqti,
48
Added:
or any adapter.
49
Added:
- `hito.import` contains the adapters for third-party exports (`Hevy_csv`). It
50
Added:
depends on `hito.core`, `hito.app`, and `csv`. It does not link a web
51
Added:
framework.
52
Added:
- `hito.persistence` contains the adapters that implement the ports:
53
Added:
`Sqlite_repo`, `Bcrypt_hash`, `Codec`, `Import_codec`, `Timestamp`, and
54
Added:
`Migrations`. SQL occurs only in this library.
55
Added:
- `hito.presenter` contains view models, routes, and pages. It depends on
56
Added:
Dream and dream-html only. It cannot name a core entity, a service, or an
57
Added:
adapter.
58
Added:
- `hito.web` contains the Dream controllers. It depends on `hito.core`,
59
Added:
`hito.app`, and `hito.presenter`. It maps entities to view models and owns
60
Added:
all user-facing wording (`Present` in `Handlers_kit`). It reaches adapters
61
Added:
only through ports.
52
62
53
Removed:
`bin/` is the composition root: it alone names both an adapter and the use
54
Removed:
case it plugs in.
63
Added:
`bin/` is the composition root. Only `bin/` names both an adapter and the use
64
Added:
case that the adapter plugs into.
55
65
56
66
Rules:
57
67
58
68
- Ports are module types. Adapters implement them. `Service.Make` and
59
69
`Handlers.Make` are the dependency inversion.
60
Removed:
- Persistence identity is assigned in `hito.app`, not in the core.
61
Removed:
- Data crossing a boundary is a plain value: a view-model DTO outward, a core
62
Removed:
type inward. Never an entity into the presenter, never a row into the core.
63
Removed:
- `pp` functions in the core are debugging output. User-facing wording lives in
64
Removed:
`hito.web`'s `Present` and nowhere inward.
70
Added:
- `hito.app` assigns persistence identity. The core does not.
71
Added:
- Data that crosses a boundary is a plain value. A view-model DTO goes outward.
72
Added:
A core type comes inward. Never send an entity into the presenter. Never
73
Added:
send a database row into the core.
74
Added:
- The `pp` functions in the core are debugging output. User-facing wording
75
Added:
occurs only in `Present` in `hito.web`.
.kiro/steering/workflow.md
@@ -2,75 +2,109 @@
2
2
3
3
## Definition of done
4
4
5
Removed:
A feature is not finished until, in this order:
5
Added:
A feature is complete only when these conditions are true, in this order:
6
6
7
Removed:
1. `dune build @check --build-dir _build-agent` is clean (type-checks library
8
Removed:
*and* tests).
9
Removed:
2. Alcotests exist for it — unit tests for behaviour, end-to-end tests for flows
10
Removed:
that cross module boundaries — and `dune runtest --build-dir _build-agent`
11
Removed:
passes.
12
Removed:
3. Formatting is applied and `dune build @fmt --build-dir _build-agent` is
13
Removed:
clean. Format with `ocamlformat --inplace` on the touched files, never
7
Added:
1. Alcotests exist for the feature. Write unit tests for behaviour. Write
8
Added:
end-to-end tests for flows that cross module boundaries.
9
Added:
2. The touched files are formatted with `ocamlformat --inplace`. Do not use
14
10
`dune fmt` (see Build directory safety).
15
Removed:
4. Documentation reflects the change.
11
Added:
3. The documentation agrees with the change.
12
Added:
4. The exact tree passes verification (see Verification ownership).
16
13
17
Removed:
Then, and only then:
14
Added:
After these conditions are true:
18
15
19
Removed:
- Commit — but only when asked.
20
Removed:
- Never commit unformatted or failing code.
21
Removed:
- Use `direnv exec . dune ...` if the local opam switch is not active.
16
Added:
- Commit only when the user asks.
17
Added:
- Do not commit code that is not formatted or that fails a check.
18
Added:
- If the local opam switch is not active, use `direnv exec . dune ...`.
22
19
20
Added:
## Verification ownership
21
Added:
22
Added:
`scripts/ci.sh` is the single full verification command. It does these checks
23
Added:
in the `_build-ci` build directory:
24
Added:
25
Added:
1. `dune build @check` type-checks the libraries and the tests.
26
Added:
2. `dune runtest --force` runs all Alcotest suites.
27
Added:
3. `dune build @fmt` makes sure that the formatting is correct.
28
Added:
29
Added:
The `.githooks/pre-push` hook runs `scripts/ci.sh` before each push.
30
Added:
`scripts/install-hooks.sh` enables the hook once for each clone.
31
Added:
32
Added:
On the deployment host, `deploy/post-receive` builds each push to `master`
33
Added:
again. It installs the dependencies, then runs `dune build @check`,
34
Added:
`dune runtest`, and a release build. It does not run the formatting check.
35
Added:
36
Added:
Apply these rules:
37
Added:
38
Added:
- A passing pre-push hook verifies the exact tree that the push sends.
39
Added:
- A passing automated build verifies its exact tree.
40
Added:
- After a successful push or pull, do not run the full checks again if
41
Added:
automation verified the exact tree.
42
Added:
- If the hook is disabled or bypassed, run `scripts/ci.sh` manually.
43
Added:
- If automated verification fails, run `scripts/ci.sh` manually.
44
Added:
- If a pull changes the tree without automated verification, run the checks
45
Added:
after the merge.
46
Added:
- If a pull causes conflicts, run the checks after you resolve them.
47
Added:
- During development, use targeted checks for fast feedback.
48
Added:
- Do not run the full suite again if the tree did not change and no
49
Added:
verification step failed or was bypassed.
50
Added:
23
51
## Commits
24
52
25
Removed:
- Follow Conventional Commits:
53
Added:
- Use Conventional Commits:
26
54
27
55
```
28
Removed:
<type>(<optional scope>): <imperative summary under 72 chars>
56
Added:
<type>(<optional scope>): <imperative summary under 72 characters>
29
57
30
Removed:
Body: why, not what. Wrap at 72. Note deviations from Heavy Duty doctrine
31
Removed:
and the reasoning behind design decisions.
58
Added:
Body: say why, not what. Wrap at 72 characters. Record each deviation
59
Added:
from Heavy Duty doctrine and the reason for each design decision.
32
60
```
33
61
34
62
- Types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `build`, `perf`.
35
Removed:
- Scopes follow the layering: `core`, `app`, `web`, plus module names
36
Removed:
(`core/set`, `core/recovery`).
37
Removed:
- Commit only when asked.
38
Removed:
- Stage specific files rather than `git add .`.
63
Added:
- Scopes follow the layers: `core`, `app`, `import`, `persistence`,
64
Added:
`presenter`, `web`, plus module names (`core/set`, `core/recovery`).
65
Added:
- Commit only when the user asks.
66
Added:
- Stage specific files. Do not use `git add .`.
39
67
40
68
## Documentation
41
69
42
Removed:
Written for a human skimming the repo, not for completeness.
70
Added:
Write for a person who reads the repository quickly. Completeness is not the
71
Added:
goal.
43
72
44
Removed:
- Terse, idiomatic OCaml documentation.
45
Removed:
- Refactor docs aggressively. Delete anything stale or redundant in the same
46
Removed:
change that outdates it.
47
Removed:
- Interface docs state **intention**, not implementation. One line where one
48
Removed:
line will do.
49
Removed:
- A module header says what the module is for and which invariant it upholds.
50
Removed:
- No Markdown files unless asked.
51
Removed:
- Do not restate the signature in prose. Document the *why* and the edge cases.
73
Added:
- Write all prose in ASD-STE100 Simplified Technical English. This rule
74
Added:
applies to steering, Org files, interface comments, and commit messages.
75
Added:
- Keep OCaml documentation short and idiomatic.
76
Added:
- When a change makes a document stale or redundant, correct or remove the
77
Added:
document in the same change.
78
Added:
- Interface comments state the intention, not the implementation. If one line
79
Added:
is sufficient, write one line.
80
Added:
- A module header states the purpose of the module and the invariant that it
81
Added:
keeps.
82
Added:
- Do not add Markdown files unless the user asks. Use Org mode for project
83
Added:
documentation.
84
Added:
- Do not repeat the signature in prose. Document the reason and the edge
85
Added:
cases.
52
86
53
Removed:
54
87
## Build directory safety
55
88
56
Removed:
Never use the default Dune build directory. A persistent `dune exec -w ogit` process may use `_build`.
89
Added:
Do not use the default Dune build directory. A persistent watch process, for
90
Added:
example `dune exec -w hito`, can use `_build`.
57
91
58
Removed:
Use these commands instead:
92
Added:
Use an isolated build directory:
59
93
60
94
- `dune build --build-dir _build-agent`
61
95
- `dune runtest --build-dir _build-agent`
62
96
63
97
Do not run `dune clean` on the default `_build` directory.
64
98
65
Removed:
Never run `dune fmt` while a watch build runs. `dune fmt` ignores
99
Added:
Do not run `dune fmt` while a watch build runs. `dune fmt` ignores
66
100
`--build-dir` and connects to the Dune RPC server that the watch process owns.
67
Removed:
Dune drops that connection mid-rebuild. The failure then looks like a build
68
Removed:
error when the code is fine.
101
Added:
Dune can drop that connection during a rebuild. The result looks like a build
102
Added:
error, but the code is correct.
69
103
70
Removed:
Format with `ocamlformat` directly, which does not touch the RPC server:
104
Added:
Format with `ocamlformat` directly. It does not use the RPC server:
71
105
72
Removed:
- `ocamlformat --inplace <files you changed>`
106
Added:
- `ocamlformat --inplace <changed files>`
73
107
74
Removed:
Then confirm with `dune build @fmt --build-dir _build-agent`, which uses the
75
Removed:
isolated build directory. Do not chain formatting after passing steps with
76
Removed:
`&&`. A dropped format connection must not mask a clean build and test run.
108
Added:
Then run `dune build @fmt --build-dir _build-agent`. This command uses the
109
Added:
isolated build directory. Do not chain the formatting step after other steps
110
Added:
with `&&`. A dropped connection must not hide a clean build and test run.
README.org
@@ -1,31 +1,33 @@
1
1
#+TITLE: hito
2
2
#+AUTHOR: Marius Peter
3
3
4
Removed:
A Heavy Duty training tracker. hito records workouts the way Mike Mentzer's
5
Removed:
Heavy Duty prescribes them: one working set to failure per exercise, recovery
6
Removed:
gating the next session, and progress measured as more reps or more load.
4
Added:
hito is a Heavy Duty training tracker. It records workouts as Mike Mentzer's
5
Added:
Heavy Duty prescribes them. Each exercise gets one working set to failure.
6
Added:
Recovery gates the next session. Progress is an increase in reps, in load, or
7
Added:
in both.
7
8
8
Removed:
The domain refuses states the doctrine cannot read. A routine cannot exceed
9
Removed:
three sets per muscle. A workout cannot begin before recovery without an
10
Removed:
explicit, recorded override. A stall is corrected by resting more and doing
11
Removed:
less, never by adding work.
9
Added:
The domain refuses states that the doctrine does not permit. A routine cannot
10
Added:
have more than three sets for each muscle. A workout cannot start before
11
Added:
recovery is complete, unless the trainee gives an explicit override. The
12
Added:
application records that override. When progress stops, the correction is
13
Added:
more rest and less work. It is never more work.
12
14
13
15
* Layout
14
16
15
Removed:
Six libraries, dependencies pointing inward only. The build graph enforces
16
Removed:
the rule: a library cannot name what it does not link.
17
Added:
The project has six libraries. All dependencies point inward. The build graph
18
Added:
enforces this rule: a library cannot name a library that it does not link.
17
19
18
Removed:
| Library | Role |
20
Added:
| Library | Contents |
19
21
|--------------------+---------------------------------------------------------------|
20
Removed:
| ~hito.core~ | Pure domain. No framework, database, or Lwt. |
21
Removed:
| ~hito.app~ | Ports (~Repository~, ~Password_hash~, ~Importer~), ~Service~. |
22
Removed:
| ~hito.import~ | Adapters for third-party exports (~Hevy_csv~). |
23
Removed:
| ~hito.persistence~ | SQLite adapter, bcrypt adapter, stored-record codecs. |
24
Removed:
| ~hito.presenter~ | View models and pages. Depends on Dream only. |
25
Removed:
| ~hito.web~ | Controllers. Maps entities to view models. |
22
Added:
| ~hito.core~ | The pure domain. No framework, database, or Lwt. |
23
Added:
| ~hito.app~ | The ports (~Repository~, ~Password_hash~, ~Importer~) and ~Service~. |
24
Added:
| ~hito.import~ | The adapters for third-party exports (~Hevy_csv~). |
25
Added:
| ~hito.persistence~ | The SQLite adapter, the bcrypt adapter, and the record codecs. |
26
Added:
| ~hito.presenter~ | The view models, routes, and pages. It depends on Dream only. |
27
Added:
| ~hito.web~ | The controllers. They map entities to view models. |
26
28
27
Removed:
~bin/~ is the composition root: it alone names both an adapter and the port
28
Removed:
it plugs into.
29
Added:
~bin/~ is the composition root. Only ~bin/~ names both an adapter and the port
30
Added:
that the adapter implements.
29
31
30
32
* Run
31
33
@@ -37,39 +39,46 @@
37
39
dune exec hito
38
40
#+end_src
39
41
40
Removed:
Configuration comes from the environment. All variables have defaults.
42
Added:
The configuration comes from the environment. Each variable has a default.
41
43
42
Removed:
| Variable | Purpose |
43
Removed:
|----------------------+-------------------------------------------------------|
44
Removed:
| ~HITO_DB~ | Caqti URI. Default ~sqlite3:local_db/hito.sqlite~. |
45
Removed:
| ~HITO_SECRET~ | Signs sessions and CSRF tokens. Set it in production. |
46
Removed:
| ~HITO_PORT~ | TCP port. Default ~8080~. The server binds loopback. |
47
Removed:
| ~HITO_VERSION~ | Deployment identifier shown in the footer. |
48
Removed:
| ~HITO_SEED~ | ~1~ seeds one account on startup. Default ~0~. |
49
Removed:
| ~HITO_SEED_PASSWORD~ | Required when ~HITO_SEED=1~. |
50
Removed:
| ~HITO_SEED_CSV~ | Hevy export imported for the seeded account. |
44
Added:
| Variable | Purpose |
45
Added:
|----------------------+----------------------------------------------------------|
46
Added:
| ~HITO_DB~ | The Caqti URI. Default: ~sqlite3:local_db/hito.sqlite~. |
47
Added:
| ~HITO_SECRET~ | Signs sessions and CSRF tokens. Set it in production. |
48
Added:
| ~HITO_PORT~ | The TCP port. Default: ~8080~. The server binds loopback. |
49
Added:
| ~HITO_VERSION~ | The deployment identifier in the footer. |
50
Added:
| ~HITO_SEED~ | ~1~ seeds one account at startup. Default: ~0~. |
51
Added:
| ~HITO_SEED_PASSWORD~ | Necessary when ~HITO_SEED=1~. |
52
Added:
| ~HITO_SEED_CSV~ | The Hevy export to import for the seeded account. |
51
53
52
Removed:
Sessions live in a signed cookie. The server sets a same-origin content
53
Removed:
security policy and refuses framing. Put a TLS-terminating proxy in front of
54
Removed:
it.
54
Added:
Sessions are in a signed cookie. The server sets a same-origin content security
55
Added:
policy and refuses framing. Put a proxy that terminates TLS in front of the
56
Added:
server.
55
57
56
58
* Develop
57
59
58
Removed:
Three gates define done, in this order. ~scripts/ci.sh~ runs all three and
59
Removed:
exits non-zero on any failure.
60
Added:
~scripts/ci.sh~ is the full verification command. It does these checks in
61
Added:
order and stops at the first failure:
60
62
61
63
#+begin_src sh
62
Removed:
dune build @check # type-check libraries and tests
63
Removed:
dune runtest # every Alcotest suite
64
Removed:
dune build @fmt # ocamlformat and dune formatting applied
64
Added:
dune build @check # type-check the libraries and the tests
65
Added:
dune runtest # run all Alcotest suites
66
Added:
dune build @fmt # make sure that the formatting is correct
65
67
#+end_src
66
68
67
Removed:
Format with ~ocamlformat --inplace~ on the files you touched. Run
68
Removed:
~scripts/install-hooks.sh~ once per clone to run the gates before every push.
69
Added:
Format the files that you change with ~ocamlformat --inplace~. Run
70
Added:
~scripts/install-hooks.sh~ once for each clone. The pre-push hook then runs
71
Added:
~scripts/ci.sh~ before each push.
69
72
73
Added:
* Deploy
74
Added:
75
Added:
~deploy/setup.sh~ prepares the deployment host. ~deploy/post-receive~ builds
76
Added:
and tests each push to ~master~, then replaces the live release. If the health
77
Added:
check fails, the hook goes back to the previous release.
78
Added:
70
79
* Doctrine
71
80
72
Removed:
Design decisions answer to /Heavy Duty I/. The steering files under
73
Removed:
~.kiro/steering/~ state the principles the model encodes and the rules the
74
Removed:
code follows. The book itself is copyrighted reference material and is not
75
Removed:
part of the repository.
81
Added:
Design decisions follow /Heavy Duty I/. The steering files in ~.kiro/steering/~
82
Added:
state the principles that the model encodes and the rules that the code
83
Added:
follows. The book is copyrighted reference material. It is not part of the
84
Added:
repository.