View raw

hito

Table of Contents

hito is a Heavy Duty training tracker. It records workouts as Mike Mentzer's Heavy Duty prescribes them. Each exercise gets one working set to failure. Recovery gates the next session. Progress is an increase in reps, in load, or in both.

The domain refuses states that the doctrine does not permit. A routine cannot have more than three sets for each muscle. A workout cannot start before recovery is complete, unless the trainee gives an explicit override. The application records that override. When progress stops, the correction is more rest and less work. It is never more work.

Layout

The project has six libraries. All dependencies point inward. The build graph enforces this rule: a library cannot name a library that it does not link.

| Library | Contents | |--------------------+---------------------------------------------------------------| | hito.core | The pure domain. No framework, database, or Lwt. | | hito.app | The ports (Repository, Password_hash, Importer) and Service. | | hito.import | The adapters for third-party exports (Hevy_csv). | | hito.persistence | The SQLite adapter, the bcrypt adapter, and the record codecs. | | hito.presenter | The view models, routes, and pages. It depends on Dream only. | | hito.web | The controllers. They map entities to view models. |

bin/ is the composition root. Only bin/ names both an adapter and the port that the adapter implements.

Run

hito needs OCaml 5.1 or later and the pinned dependencies in hito.opam.

opam install . --deps-only --with-test
dune build
dune exec hito

The configuration comes from the environment. Each variable has a default.

| Variable | Purpose | |----------------------+----------------------------------------------------------| | HITO_DB | The Caqti URI. Default: sqlite3:local_db/hito.sqlite. | | HITO_SECRET | Signs sessions and CSRF tokens. Set it in production. | | HITO_PORT | The TCP port. Default: 8080. The server binds loopback. | | HITO_VERSION | The deployed commit date in YYYYMMDD format. | | HITO_SEED | 1 seeds an account at startup. Development defaults to 1. Deployment defaults to 0. | | HITO_SEED_PASSWORD | Password for the deployment seed when HITO_SEED=1. | | HITO_SEED_CSV | The Hevy export for the deployment seed. |

Sessions are in a signed cookie. The server sets a same-origin content security policy and refuses framing. Put a proxy that terminates TLS in front of the server.

When the version is development, startup creates the local account test with password test. It selects the Ideal Routine and adds 39 complete native workouts across the past 90 days. Set HITO_SEED=0 to disable this fixture. Deployments default to no seed. An explicit deployment seed still uses HITO_SEED_PASSWORD and HITO_SEED_CSV.

Develop

scripts/ci.sh is the full verification command. It does these checks in order and stops at the first failure:

dune build @check      # type-check the libraries and the tests
dune runtest           # run all Alcotest suites
dune build @fmt        # make sure that the formatting is correct

Format the files that you change with ocamlformat --inplace. Run scripts/ci.sh when you need local verification. The deployment server verifies each candidate master revision before it accepts the update.

Deploy

deploy/setup.sh prepares the deployment host. Its install subcommand installs the trusted CI helper and the receive hooks. Run it again after a hook or CI helper update.

The pre-receive hook archives and verifies a candidate master revision before Git updates master. A failed check rejects the push. The post-receive hook builds and replaces the live release only after that check passes. The server installs test and formatting dependencies for verification.

A client hook is a local safeguard. A clone can omit or bypass it. The pre-receive hook is the authority for master and deployment safety.

Doctrine

Design decisions follow /Heavy Duty I/. The steering files in .kiro/steering/ state the principles that the model encodes and the rules that the code follows. The book is copyrighted reference material. It is not part of the repository.