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
3 changes: 2 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ on:
- main
tags: '*'
pull_request:

types: [labeled, synchronize, opened, reopened]

jobs:
call:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run ci')
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/Documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ on:
- main
tags: '*'
pull_request:

types: [labeled, synchronize, opened, reopened]

jobs:
call:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'run documentation')
Expand Down
12 changes: 12 additions & 0 deletions BREAKINGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

This document outlines all breaking changes introduced in CTBase v0.18.0-beta compared to v0.17.4. Use this guide to migrate your code and understand the impact of these changes.

## Non-breaking note (0.18.15-beta)

- **Philosophy documentation**: Added comprehensive code philosophy documentation in `dev/philosophy/` covering modules, types/traits, exceptions, docstrings, testing, and documentation standards. No API changes; purely documentation additions.
- **Agent guides**: Added `AGENTS.md` and `CLAUDE.md` for agent navigation and project context. No API changes; purely documentation additions.
- **Documentation build improvements**: Changed `docs/make.jl` build method and fixed cross-references. No API changes; purely documentation improvements.
- **Typed exceptions**: Replaced untyped `error()` and `ArgumentError` with structured CTBase exceptions in `ext/` files. No API changes; internal error handling improvement.
- **Import qualification**: Qualified imports in submodules (`using DocStringExtensions` → `import DocStringExtensions: TYPEDEF, TYPEDSIGNATURES`). No API changes; internal code quality improvement.
- **Code cleanup**: Removed dead ternary branches, fixed byte-indexing, removed circular imports. No API changes; internal code quality improvement.
- **TestRunner auto-discovery fix**: Fixed non-recursive test discovery in auto-discovery mode. No API changes; bug fix.
- **Docstring refactoring**: Rewrote ExtensionError and SolverFailure docstrings with `$(TYPEDEF)` and standardized sections. No API changes; documentation improvement.
- **No migration required**: All changes are internal or documentation-only. No breaking changes.

## Non-breaking note (0.18.14-beta)

- **TestRunner progress display refactoring**: Renamed `progress` parameter to `show_progress_line` for clarity, and added new `show_progress_bar` parameter for granular control. Users with `progress=false` should change to `show_progress_line=false`. Users with `progress=true` (default) can keep using defaults or set `show_progress_line=true, show_progress_bar=false` for minimal display without the graphical bar. No breaking changes; purely parameter rename with backward-compatible defaults. Migration: replace `progress=` with `show_progress_line=`.
Expand Down
65 changes: 65 additions & 0 deletions CHANGELOGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,71 @@ All notable changes to CTBase will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.18.15-beta] - 2026-06-06

### 📚 Documentation

#### **Philosophy Documentation**

- **Added philosophy documentation**: Added comprehensive code philosophy documentation in `dev/philosophy/`
- `modules.md`: Submodule organization, imports/qualification, DAG, exports
- `types-traits-interfaces.md`: Types vs traits, interfaces/contracts, SOLID/DRY/YAGNI, type stability
- `exceptions.md`: The 7 exceptions and the choice rule
- `docstrings.md`: Docstring templates, cross-references, example safety
- `testing.md`: Categories, fakes/stubs, module + callable function template
- `documentation.md`: API generation, guides, draft workflow
- **Added agent guides**: Added `AGENTS.md` (agent navigation guide) and `CLAUDE.md` (Claude project context)
- **Added planning template**: Added `dev/planning.md` for implementation plans
- **Added operational rules**: Added `dev/RULES.md` for MCP, doc build, git, and output capture procedures

#### **Documentation Build Improvements**

- **Faster builds**: Changed `docs/make.jl` from `Pkg.activate/instantiate` to `pushfirst!(LOAD_PATH, ...)` for faster builds
- **Fixed cross-references**: Fixed unresolved `@ref` links for extension tags (AbstractCoveragePostprocessingTag, TestRunnerTag, AbstractTestRunnerTag)
- **Added examples**: Added example code blocks for extension tags in docstrings
- **Refactored docstrings**: Rewrote ExtensionError and SolverFailure docstrings with `$(TYPEDEF)`, standardized sections, and cross-references

### 🐛 Bug Fixes

#### **TestRunner Auto-Discovery**

- **Fixed non-recursive discovery**: Fixed test discovery in auto-discovery mode to use `_collect_test_files_recursive` instead of flat `readdir`
- **Impact**: Tests in subdirectories were silently ignored in auto-discovery mode; now properly collected recursively

#### **Typed Exceptions (Tenet 6)**

- **Replaced untyped errors**: Replaced all `error()` and `ArgumentError` with structured CTBase exceptions across `ext/` files
- `ext/TestRunner.jl`: 7 replacements (IncorrectArgument, PreconditionError)
- `ext/CoveragePostprocessing.jl`: 4 replacements (PreconditionError)
- `ext/DocumenterReference.jl`: 2 replacements (IncorrectArgument)
- **Fixed invalid Julia syntax**: Fixed 2 occurrences of `catch e::CTBase.Exceptions.CTException` → `catch e` + `e isa ... || rethrow()`
- **Fixed docstring output**: Corrected incorrect output in `_progress_bar` docstring (width=20 → 10 blocks)
- **Updated tests**: Updated 7 test files to reflect new exception types

### 🧹 Code Quality

#### **Import Qualification**

- **Qualified imports**: Changed `using DocStringExtensions` to `import DocStringExtensions: TYPEDEF, TYPEDSIGNATURES` in all submodules
- **Qualified Coverage import**: Changed `using Coverage` to `using Coverage: Coverage` in CoveragePostprocessing
- **Removed circular import**: Removed `using CTBase` from src/Exceptions/Exceptions.jl
- **Removed redundant imports**: Removed redundant `using DocStringExtensions` from src/Descriptions/types.jl

#### **Code Cleanup**

- **Removed dead ternary branches**: Simplified `_normalize_selections` and `_builder_to_string` in TestRunner
- **Fixed byte-indexing**: Changed path slicing from byte-indexing to `relpath()` in CoveragePostprocessing
- **Fixed collision risk**: Normalized flat names in cov file flattening to prevent collisions

### 🧪 Testing

- **All tests pass**: 1161/1161 tests pass
- **Documentation builds**: Documentation builds successfully with no extension errors

### 🧹 Maintenance

- **Version bump**: Bumped to 0.18.15-beta for development.

## [0.18.14-beta] - 2026-05-30

### ✨ New Features
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "CTBase"
uuid = "54762871-cc72-4466-b8e8-f6c8b58076cd"
version = "0.18.14-beta"
version = "0.18.15-beta"
authors = ["Olivier Cots <olivier.cots@irit.fr>", "Jean-Baptiste Caillau <caillau@univ-cotedazur.fr>"]

[deps]
Expand Down
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[deps]
CTBase = "54762871-cc72-4466-b8e8-f6c8b58076cd"
Coverage = "a2441757-f6aa-5fb2-8edb-039e3f45d037"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
MarkdownAST = "d0879d2d-cac2-40c8-9cee-1863dc0c7391"
Expand Down
39 changes: 15 additions & 24 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,29 @@ The documentation is built using [Documenter.jl](https://github.com/JuliaDocs/Do

## Building the Documentation

There are several ways to build the documentation locally.

### 1. Terminal One-Liner (Recommended)

From the root of the `CTBase.jl` repository, run:
From the root of the repository:

```bash
julia --project=docs/ -e 'using Pkg; Pkg.develop(path=pwd()); include("docs/make.jl"); Pkg.rm("CTBase")'
julia --project=. docs/make.jl
```

This command:
- Activates the `docs` project environment.
- Temporarily "develops" the current package so changes are reflected in the build.
- Executes `make.jl` to build the site.
- Cleans up the `docs` environment by removing the temporary link to `CTBase`.

### 2. Manual REPL Build
`make.jl` prepends both `docs/` and the package root to `LOAD_PATH`, so the package
project is picked up automatically — no `Pkg.develop` step needed.

If you prefer working inside the Julia REPL:
### Draft mode (fast link validation)

```julia
# 1. Activate the docs project
using Pkg
Pkg.activate("docs/")
Set `draft = true` at the top of `docs/make.jl` to skip `@repl`/`@example` block
execution. This is much faster when iterating on cross-references and page structure:

# 2. Add CTBase in development mode (if not already done)
Pkg.develop(path=pwd())

# 3. Build the documentation
include("docs/make.jl")
```bash
# edit docs/make.jl: draft = true (line 16)
julia --project=. docs/make.jl
```

!!! note "warnonly"
`make.jl` uses `warnonly=[:cross_references]`, so cross-reference warnings do not
abort the build. Other errors (missing pages, broken `@repl` blocks) still fail.

## Viewing the Documentation

After a successful build, the generated HTML files are located in `docs/build/`. You can open `index.html` in your browser:
Expand All @@ -54,7 +45,7 @@ xdg-open docs/build/index.html

## Directory Structure

- `src/`: Contains the manual markdown files (Introduction, Tutorials, etc.).
- `src/`: Contains the manual markdown files (Introduction, Getting Started, Guides, etc.).
- `make.jl`: The main build script for Documenter.
- `api_reference.jl`: Contains the logic for automatic API reference generation. It extracts docstrings from the source code and creates temporary markdown files.
- `build/`: The directory where the static website is generated (ignored by git).
Expand Down
11 changes: 6 additions & 5 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Pkg
Pkg.activate(@__DIR__)
Pkg.develop(PackageSpec(; path=joinpath(@__DIR__, "..")))
Pkg.instantiate()
# to run the documentation generation:
# julia --project=. docs/make.jl
pushfirst!(LOAD_PATH, joinpath(@__DIR__))
pushfirst!(LOAD_PATH, joinpath(@__DIR__, ".."))

using Documenter
using CTBase
Expand Down Expand Up @@ -54,7 +54,7 @@ with_api_reference(src_dir) do api_pages
makedocs(;
draft=draft,
remotes=nothing, # Disable remote links. Needed for DocumenterReference
warnonly=true,
warnonly=[:cross_references],
sitename="CTBase.jl",
format=Documenter.HTML(;
repolink="https://" * repo_url,
Expand All @@ -67,6 +67,7 @@ with_api_reference(src_dir) do api_pages
),
pages=[
"Introduction" => "index.md",
"Getting Started" => "getting-started.md",
"User Guides" => [
"Descriptions" => joinpath("guide", "descriptions.md"),
"Exceptions" => joinpath("guide", "exceptions.md"),
Expand Down
114 changes: 114 additions & 0 deletions docs/src/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
```@meta
CurrentModule = CTBase
```

# Getting Started

## Installation

CTBase.jl is typically installed as a dependency of another package in the ecosystem
(e.g. [OptimalControl.jl](https://github.com/control-toolbox/OptimalControl.jl)).
To install it directly:

```julia
import Pkg
Pkg.add("CTBase")
```

**Requires Julia ≥ 1.10.**

## Mental Model

CTBase is the **base layer** of the control-toolbox ecosystem.
It provides infrastructure shared by every package above it.

Three things to keep in mind:

1. **No top-level exports.** `using CTBase` loads the package but brings no symbols
into scope. Every symbol is accessed via its qualified path:
```julia
CTBase.Descriptions.add # ✓ always works
CTBase.Exceptions.NotImplemented
```
2. **Submodule-first API.** The public API lives in named submodules
(`Descriptions`, `Exceptions`, `Extensions`, `Core`, `Unicode`).
You can bring a submodule's exports into scope explicitly:
```julia
using CTBase.Exceptions # brings IncorrectArgument, NotImplemented, … into scope
```
3. **Extension-backed features.** `run_tests`, `postprocess_coverage`, and
`automatic_reference_documentation` require loading the matching weak dependency
(`Test`, `Coverage`, `Documenter` respectively) before they become active.

## 5-Minute Walkthrough

### Working with Descriptions

A *description* is a `Tuple` of `Symbol`s that declaratively identifies an algorithm
or configuration. Catalogues collect known descriptions; `complete` resolves a partial
description to an exact one.

```@repl walkthrough
using CTBase

# Build a catalogue
descs = CTBase.Descriptions.add((), (:euler, :explicit))
descs = CTBase.Descriptions.add(descs, (:euler, :implicit))
descs = CTBase.Descriptions.add(descs, (:runge_kutta, :explicit))

# Partial completion: find the unique entry containing :implicit
CTBase.Descriptions.complete(:implicit; descriptions=descs)

# Ambiguous completion raises AmbiguousDescription
try
CTBase.Descriptions.complete(:euler; descriptions=descs)
catch e
println(typeof(e))
end
```

For more, see the **[Descriptions guide](guide/descriptions.md)**.

### Working with Exceptions

CTBase defines a typed exception hierarchy rooted at
[`CTBase.Exceptions.CTException`](@ref).
Each type carries structured context fields for actionable error messages.

```@repl walkthrough
# IncorrectArgument — invalid input value
try
throw(CTBase.Exceptions.IncorrectArgument(
"state dimension must be positive";
got="0",
expected="n > 0",
suggestion="Pass a positive integer for the state dimension",
))
catch e
println(e)
end

# NotImplemented — interface stub
try
throw(CTBase.Exceptions.NotImplemented(
"solve! is not implemented";
required_method="solve!(::MyStrategy, ocp)",
suggestion="Import the package that provides this strategy",
))
catch e
println(typeof(e))
end
```

For more, see the **[Exceptions guide](guide/exceptions.md)**.

## Next Steps

| Topic | Guide |
|:---|:---|
| Descriptions catalogue and completion | [Descriptions](guide/descriptions.md) |
| Exception hierarchy and best practices | [Exceptions](guide/exceptions.md) |
| Modular test runner setup | [Test Runner](guide/test-runner.md) |
| Coverage report generation | [Coverage](guide/coverage.md) |
| Auto-generated API reference | [API Documentation](guide/api-documentation.md) |
| Full API reference | API Reference (left sidebar) |
6 changes: 5 additions & 1 deletion docs/src/guide/api-documentation.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
```@meta
CurrentModule = CTBase
```

# API Documentation Guide

This guide explains how to set up automated API reference documentation generation using the **DocumenterReference** extension of `CTBase.jl`. This is particularly useful for maintaining comprehensive and up-to-date API documentation as your codebase evolves.

## Overview

The `DocumenterReference` extension provides the `CTBase.automatic_reference_documentation()` function, which automatically generates API reference pages from your Julia source code. It:
The `DocumenterReference` extension provides the [`CTBase.automatic_reference_documentation`](@ref) function, which automatically generates API reference pages from your Julia source code. It:

- Extracts docstrings from your modules
- Separates public and private APIs
Expand Down
7 changes: 6 additions & 1 deletion docs/src/guide/coverage.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
CurrentModule = CTBase
```

# Coverage Post-processing Guide

This guide explains how to generate human-readable and machine-parseable coverage reports using the **CoveragePostprocessing** extension of `CTBase.jl`.
Expand Down Expand Up @@ -25,14 +29,15 @@ To generate actionable coverage reports, we use a dedicated `coverage.jl` script
pushfirst!(LOAD_PATH, @__DIR__)

using Pkg
using CTBase # Provides postprocess_coverage
using CTBase # Provides CTBase.postprocess_coverage
using Coverage

# This function:
# 1. Aggregates coverage data.
# 2. Generates an LCOV file (coverage/lcov.info).
# 3. Generates a markdown summary (coverage/cov_report.md).
# 4. Archives used .cov files to keep the directory clean.
# See: CTBase.postprocess_coverage
CTBase.postprocess_coverage(;
root_dir=dirname(@__DIR__) # Point to the package root
)
Expand Down
Loading
Loading