Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 32 additions & 24 deletions docs/reports/99-api-coverage.md → docs/api-coverage.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
# API coverage matrix

**Status**: specification · **Generated from**: `names(OptimalControl)` on
OptimalControl 2.1.0-beta, resolved environment (CTBase 0.28.9-beta, CTModels 0.15.3-beta,
CTFlows 0.16.3-beta, CTLie 0.1.5-beta, CTSolvers 0.4.34-beta)
**Status**: living cross-reference · **Measured against**: `names(OptimalControl)` on
OptimalControl 2.2.0-beta (`[compat]` floors CTBase 0.30, CTModels 0.19, CTFlows 0.18,
CTLie 0.2, CTSolvers 0.5, CTDirect 1, CTParser 0.9)

## What this is

The objective acceptance criterion for the whole rewrite: **every exported symbol appears in
at least one guide page and in exactly one API-reference theme.**

`names(OptimalControl)` returns **193 symbols** (excluding `:OptimalControl` itself). They are
partitioned below. A symbol with an empty *Guide* cell is a hole — either a page must cover it
or it must be justified as reference-only.
The *theme* half is enforced by the docs build: `docs/api_reference.jl` (lines ~361–389)
`error`s the build if any exported symbol is absent from `API_THEMES`, or if a theme lists a
name that is neither exported nor `qualified`. This file is the **guide-side** cross-reference
the build cannot check — which page actually teaches each symbol.

`names(OptimalControl)` returns **203 symbols** (excluding `:OptimalControl` itself). Sections
§§1–11 below partition **200** of them; the remaining **3** — `Lie`, `⋅`, `HamiltonianLift`
(§13, the deprecated shims re-introduced by PR 3, now real exported bindings) — bring the
total to 203. A symbol with an empty *Guide* cell is a hole — either a page must cover it or
it must be justified as reference-only.

Regenerate the ground truth with:

Expand All @@ -21,10 +28,11 @@ julia --project=. -e 'using OptimalControl;
println(length(ns)); foreach(println, ns)'
```

PR 4 wires the same computation into `docs/api_reference.jl` as a build-time check
([`09-api-reference.md`](09-api-reference.md) §"The completeness check").
`docs/api_reference.jl` runs the same computation as a build-time completeness check (the
`let` block after `API_THEMES`).

Page ids refer to the sitemap in [`00-cahier-des-charges.md`](00-cahier-des-charges.md) §7.
Page ids are the `@id` anchors declared on the pages under `docs/src/` (e.g.
`modelling-abstract-syntax` on `modelling/abstract-syntax.md`).

---

Expand Down Expand Up @@ -58,7 +66,7 @@ Re-exported so generated code and macro expansions can qualify. Not user-facing
| `time!` `state!` `control!` `variable!` `dynamics!` `objective!` `constraint!` `time_dependence!` `build` | `modelling-functional-api` | modelling |
| `build_initial_guess` | `solve-initial-guess` | modelling |

## 4. Problem introspection — 47
## 4. Problem introspection — 58

All on `modelling-inspect` unless noted; API theme **problem**.

Expand All @@ -79,7 +87,7 @@ All on `modelling-inspect` unless noted; API theme **problem**.
`dynamics` `mayer` `lagrange` `has_mayer_cost` `has_lagrange_cost`
`is_mayer_cost_defined` `is_lagrange_cost_defined`

**Constraints (11)**
**Constraints (12)**
`constraint` `constraints` `path_constraints_nl` `boundary_constraints_nl`
`state_constraints_box` `control_constraints_box` `variable_constraints_box`
`dim_path_constraints_nl` `dim_boundary_constraints_nl` `dim_state_constraints_box`
Expand Down Expand Up @@ -130,7 +138,7 @@ All on `results-solution` unless noted; API theme **solution**.
`dim_dual_state_constraints_box` `dim_dual_control_constraints_box`
`dim_dual_variable_constraints_box`

## 7. Options and strategies — 22
## 7. Options and strategies — 25

All on `solve-options` or `solve-choosing-a-method`; API theme **options**.

Expand All @@ -143,7 +151,7 @@ All on `solve-options` or `solve-choosing-a-method`; API theme **options**.
| `parameter` `default_parameter` `available_parameters` | `solve-gpu` |
| `CPU` `GPU` | `solve-gpu` |

## 8. Flows — 24
## 8. Flows — 26

API theme **flows**.

Expand All @@ -166,10 +174,9 @@ their siblings `control_law` and `pseudo_hamiltonian` were — PR 8 closed the g
accessors — gradients and vocabulary" testset). `system` and `integrator` stay deliberately
unexported — qualified as `CTFlows.Flows.system(f)`.

`length(names(OptimalControl)) - 1` measured **203** after this change, not the **200** this
report anticipated (193 + 7) — a 3-symbol drift accumulated somewhere between this report's
original count and PR 8, unrelated to this PR's own +7. Not audited/reconciled here; flagging
for whoever next touches this file's top-line count.
PR 8 brought the count from 193 to 200 (+7 here); the remaining 3 of the current 203 are the
§13 deprecated shims (`Lie`, `⋅`, `HamiltonianLift`), which PR 3 made real exported bindings.
Reconciled 2026-09 during E6-C.

## 9. Geometry — 7

Expand Down Expand Up @@ -272,13 +279,14 @@ Recorded so they are decided, not forgotten.
| `SolverFailure` is exported by `CTBase.Exceptions` but imported nowhere in OptimalControl | §12 | open — PR 3: surface it or note the omission |
| CTModels init helpers not re-exported: `initial_guess`, `pre_initial_guess`, `validate_initial_guess`, `initial_state`, `initial_control`, `initial_variable`, `PreInitialGuess` | §3 | open — PR 5/6 |
| `@def_exa` exists in CTParser but is not re-exported | §2 | open — PR 5 |
| `time` and `success` are `Base` names with no OptimalControl binding | §13 | open — PR 3 |
| `time` and `success` are `Base` names with no OptimalControl binding | §13 | ✅ closed — PR 3 added throwing `Base.time`/`Base.success` methods (`src/deprecated.jl`) |

## 15. How to use this file

1. When a docs PR is written, tick its symbols off by filling the *Guide* column with the page
that actually covers them (not the one that was planned).
2. Before merging PR 12, re-run the `names(OptimalControl)` command above and diff against
§§1–11. A new symbol with no row is a missing docs change.
3. After PR 4, the build itself reports missing and stale symbols; this file becomes the
record of the *guide*-side coverage, which the build cannot check.
1. When a docs page changes what it covers, update the *Guide* column to the page that
actually teaches the symbol.
2. When the API surface changes, re-run the `names(OptimalControl)` command above and diff
against §§1–11 + §13. The docs build already fails on an uncovered *theme*; this file is
the *guide*-side record the build cannot check.
3. Keep the top-line count and the per-section subtotals in sync with the body — they are
documentation, not the enforced contract (that is `docs/api_reference.jl`).
8 changes: 4 additions & 4 deletions docs/api_reference.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# Thematic API reference manifest.
#
# Each theme is a literal, hand-maintained list of symbols — no scraping of
# docs/reports/99-api-coverage.md. That file is prose meant for a human to
# docs/api-coverage.md. That file is prose meant for a human to
# read and copy from, not a machine-parseable format: an earlier version of
# this script tried to extract symbols from it automatically and silently
# picked up names from sentences that explicitly said *not* to document them
# (e.g. "solve_explicit ... not documented as available"), and lost the
# module qualification some symbols need to resolve in `@docs` (a bare
# `constraint` does not resolve; `CTModels.Components.constraint` does).
#
# When 99-api-coverage.md changes, update the lists below by hand and rerun
# When docs/api-coverage.md changes, update the lists below by hand and rerun
# `julia --project=docs docs/make.jl` to check the completeness error and the
# build log for new "undefined binding" / "no docs found" warnings.

const EXCLUDE_SYMBOLS = [:include, :eval, :OptimalControl]

# Re-exported purely as escape hatches for generated code / cross-package
# qualification (see docs/reports/99-api-coverage.md §1 "Module aliases").
# qualification (see docs/api-coverage.md §1 "Module aliases").
# They carry no docstring of their own (`@doc` on a bare module without one
# resolves to Julia's generic "here are its exports" filler, identical across
# all of them — not worth transcluding). Described in prose on qualified.md
Expand Down Expand Up @@ -351,7 +351,7 @@ const API_THEMES = [
# ::Symbol...)"`): the key is what the coverage check sees, the value is the exact
# signature written into the `@docs` block. Needed whenever a bare name would pull in
# a foreign package's docstring for the same generic function (`:solve` collides with
# `CommonSolve.solve`, `:methods` with `Base.methods` — see docs/reports/99-api-coverage.md
# `CommonSolve.solve`, `:methods` with `Base.methods` — see docs/api-coverage.md
# and control-toolbox/OptimalControl.jl's Phase D campaign report for how this was found).
_bare_name(s::Symbol) = Symbol(split(String(s), ".")[end])
_bare_name(p::Pair) = _bare_name(first(p))
Expand Down
Loading
Loading