Gyredocs
Depth Practice
API

Gyre/Software Engineering

Development process

In one minuteHow the project is organised for contributors — human or agent: the roadmap as hand-off state, the effort ledger, commit and verification discipline, and the conventions that keep four interfaces consistent.

Written at L2 Practice goes to L4 Theory 1000 words Markdown
bash
make bootstrap       # .venv with uv (handles CPUs without AVX2 and NVIDIA GPUs)
make test            # unit and integration tests        make test-service   # end-to-end service
make lint            # ruff                              make docs           # build the site into site/
make verify          # verification studies -> var/verification, rendered by the docs
make ci              # the whole pipeline with stage caching

Read devlog/ROADMAP.md first (decisions, milestones, status log, open items), then CLAUDE.md (environment, conventions, definition of done). A numerical change is done when the invariants, the affected verification studies and the derivative checks pass and the documentation is updated. Gyre contains no optimizer and must not grow one.

Hand-off state#

Three files let anyone resume work cold:

  • devlog/ROADMAP.md — mission, decision table, milestones, dated status log;
  • CLAUDE.md — environment constraints, commands, conventions, definition of done;
  • devlog/time.jsonl — the effort ledger (python3 tools/worklog.py report).

The project brief asked for effort split roughly 70 % core capability, 25 % testing and verification, 10 % logistics and tooling (targets that sum to 105 %). The split is recorded in an append-only ledger, part live and part entered afterwards. The measured split, the rule by which it is compared with the target, and what limits its accuracy are on the effort ledger page, which is generated from the ledger.

Definition of done for numerical changes#

  1. Unit invariants pass (free-stream preservation, conservation, entropy balance, split-argument blocks against a dense Jacobian, dot-product identity).
  2. Affected verification studies pass (gyre verify --only …).
  3. Derivatives are checked against finite differences.
  4. Documentation is updated at the appropriate depth level and builds without broken links.

Releasing a state#

The documentation marks a verification record whose revision is neither the revision the site was built from nor its parent. A release therefore has a fixed order:

  1. Freeze. Tests green, code committed: revision X.
  2. Verify. Run the whole suite on a clean checkout of X (a separate git worktree leaves the working tree free). Every record is then stamped X, not dirty.
  3. Record. Commit the records as the direct child of X, together with prose that describes the run (its size and duration) if any.
  4. Deploy from that commit: the served pages show each record as “parent revision of this build”.

make ci does the same in one pipeline (tests, verification, documentation, image, deployment on the CI port). Later commits that change only documentation text, evidence records or bookkeeping leave the records valid: the pages then mark them “same code as this build”. A commit that changes code, tests, tools or the documentation theme makes every record a mismatch until the suite has run again (what makes a revision dirty).

Conventions that prevent drift#

  • New capability goes into the discipline or runner first, then REST, then MCP — never the other way round.
  • Reference pages (case schema, presets, CLI, REST routes, MCP tools) are generated from the code at documentation build time (gyre.docgen).
  • Verification pages render study files; text may interpret numbers but must not restate them by hand.
  • Sample or synthetic data never appears outside the authoring guide, and is labelled there.
  • Tooling is project-local (.tools/bin/uv, .venv/); no system packages are required.
  • CPUs without AVX2 need jax < 0.12 (the bootstrap script detects this).
  • Services bind 0.0.0.0; port 8600 is the development deployment, 8601 the CI deployment.
  • Scratch scripts must not shadow standard-library module names — a bisect.py next to a script breaks import jax through random → bisect.
  • A mesh generator bug looked like a solver bug. Cosine clustering left zero parametric speed at the aerofoil trailing edge; the singular Jacobian there stalled Newton at a residual of 10−310^{-3} with a nonsensical entropy level. A mesh-quality check (minimum scaled Jacobian) found it immediately; such a check is now part of the mesh tests.
  • Measure the measurement — and test the explanation. Several verification failures were caused by the study, not the code: an ill-conditioned finite difference, a step sweep that left the smooth regime, a mesh too coarse to represent the geometry. One plausible explanation (“time-integration error dominates at p=4p = 4”) was itself wrong and was caught only because the fix was verified to change the numbers — it did not.
  • Warm starts need their own convergence logic. Re-solving from a converged neighbour first restarted pseudo-time continuation at low CFL, then chased a tolerance relative to its own tiny initial residual. Sessions now start in the Newton regime and converge relative to the cold-solve residual scale.
  • One definition of “which code is this”. Result files and the service reported the revision through one function; verification records and the documentation build through an older copy that called any uncommitted file dirty, the effort ledger and the records themselves included. A verification run on a clean checkout stamped every record after the first as dirty. The stamp now has a single source.
  • A strict failure policy finds what a permissive one hides. When a linear solve that misses its tolerance became an error, the adjoint of the turbulent flat plate stopped: on a wall-resolved mesh block Jacobi alone had been returning derivatives from a solve that had not converged. The coarse multigrid level fixes it; the policy stays.
  • A threshold belongs to a regime. The manufactured solution of the turbulence closure demanded the design rate and measured half an order less. The eddy viscosity had moved the mean flow into the regime where the laminar discretization converges at that rate too: the study now solves the laminar problem at the effective Reynolds number and requires the closure to change neither the order nor the error.
  • Reverse mode through a chunked loop stores the loop. The matrix-free mesh deformation recomputes its weights chunk by chunk, but differentiating it in reverse mode kept the weights of every chunk, the dense matrix it was meant to avoid. Its transpose is written out by hand as a second chunked loop.
  • Compilation is the user-visible cost. For small cases tens of seconds of JIT dwarf milliseconds of solve; this shaped sessions, the persistent cache, per-job device selection and test-suite structure.

    ↑ ↓ moveEnter open[ ] change depthResults show section and depth level