All notable changes to this project are documented in this file.
This project follows semantic versioning.
- Deterministic governance snapshots via
course-engine snapshot- Emits minimal, facts-only, diff-friendly records suitable for:
- CI change tracking,
- QA and governance review,
- reproducible audit workflows.
- Supports both:
- source snapshots (derived directly from
course.yml), and - artefact snapshots (manifest-backed, canonical).
- source snapshots (derived directly from
- Emits minimal, facts-only, diff-friendly records suitable for:
- Snapshot determinism guarantees
- Snapshot output is stable across runs.
- Non-determinism is limited to the explicitly declared
generated_at_utcfield.
- Explain pipeline clarified and hardened
- Clear separation between:
- source explain (strict, pre-normalisation YAML declarations), and
- artefact explain (canonical, manifest-backed facts).
- Artefact explain is explicitly treated as the authoritative record for QA, audit, automation, and governance workflows.
- Clear separation between:
- Release verification contracts encoded
- Maintainer verification (
scripts/verify-release.sh) now explicitly asserts:- preflight contract stability,
- explain determinism,
- snapshot reproducibility,
- pack integrity.
- Maintainer verification (
- Smoke test coverage expanded
- Smoke tests now exercise snapshot generation, explain outputs, and pack composition end-to-end without introducing enforcement.
- No course schema changes
- No new validation or enforcement behaviour
- No impact on build or render outputs
- Snapshot and explain outputs are facts-only and policy-agnostic
- Fully backward compatible with v1.20.0
-
CI-grade preflight contract for
course-engine checkwith:- deterministic, documented exit codes
- explicit workflow requirements declared in JSON output (
requirementsblock)
-
Deterministic preflight exit codes
0— OK (or informational mode)2— required tooling missing (e.g. Quarto) when required3— PDF toolchain not ready when required4— filesystem/temp-write diagnostic failed1— unexpected/internal error
-
Strict and targeted requirement modes
course-engine check --strictenables CI-grade gating (Quarto + PDF required)course-engine check --require pdfrequires PDF readiness (and implies Quarto requirement)
-
Requirements block in JSON payload
course-engine check --format jsonnow includes:mode:"default"or"strict"require_quarto,require_pdf,require_pandoc: booleans indicating what the workflow requires
- Preflight output now cleanly separates:
- environment inspection (facts),
- requirement declaration (intent),
- exit semantics (decision).
- No course schema changes
- No validation or enforcement behaviour introduced
- Fully backward compatible with v1.19 workflows (including
check --json) - Default
course-engine checkremains informational and exits0
course-engine check --format json|textoutput selector for explicit, script-safe preflight output.- Human-readable preflight output mode (
--format text) including:- Python version + platform
- Quarto + Pandoc presence/version
- PDF toolchain readiness
- actionable remediation guidance
course-engine check --jsonis now explicitly documented as a legacy/compatibility flag (prefer--format json).- Preflight JSON output is treated as a stable, machine-readable diagnostic payload suitable for CI/support workflows.
- No schema changes
- No validation or enforcement behaviour introduced
- Fully backward compatible with existing
check --jsonworkflows
-
Profile-based governance pack composition
course-engine packnow enforces explicit profiles:auditqaminimal
- Profiles determine which factual artefacts are included in a pack.
- Profile selection is validated at the CLI layer.
-
Facts-only pack README generation
- Each governance pack now includes a generated
README.txtdescribing:- pack purpose and non-purpose,
- profile used,
- included artefacts,
- generation context.
- README content is non-evaluative and governance-safe by design.
- Each governance pack now includes a generated
- Strict CLI validation for pack profiles
- Invalid
--profilevalues are rejected immediately with clear error messages. - Prevents ambiguous or partial governance outputs.
- Invalid
- No schema changes
- No validation or enforcement behaviour introduced
- No impact on build or render outputs
- Fully backward compatible with v1.17.0
- This release completes the governance packaging workflow.
- Pack generation remains:
- deterministic,
- facts-only,
- policy-agnostic.
- Restored and stabilised
python -m course_engineentrypoint - Clarified Typer callback vs entrypoint structure
- No functional changes to governance pack outputs
- build: prints a copy/paste-ready resolved artefact path (
ARTEFACT=...) on success. - pack: accepts either an artefact directory or a parent OUT directory containing exactly one artefact subdirectory (auto-detected via
manifest.json). - pack: improved failure messages for ambiguous or unrecognised directories, including candidate listings.
- tests: added coverage for parent-OUT auto-detection and multi-candidate failure behaviour.
- cli: supports
python -m course_engine.cli ...module execution.
- Hardened release and smoke-test workflows to consistently operate on the correct artefact directory
(i.e. the directory that actually contains
manifest.json, not its parent). - Ensured published version is fully aligned and verifiable across:
- CLI (
course-engine --version) - Python package metadata
- Build artefact manifests
- CLI (
- Clarified maintainer expectations around build output paths in verification and packing workflows.
- Eliminated a common maintainer error where
explain,validate, orpackwere run against a parent output directory rather than the generated artefact subdirectory. - Smoke tests now reliably detect and resolve the correct artefact path before running explain, validate, and pack steps.
- No schema changes
- No validation or enforcement changes
- No impact on build or render outputs
- Fully backward compatible with v1.15.0
- This is a release hygiene and workflow correctness update.
- It improves maintainer confidence, CI reliability, and governance reproducibility without changing user-facing behaviour.
explainnow correctly distinguishes between:- course project directories (source
course.yml) - built artefact directories (
manifest.json)
- course project directories (source
- Summary output no longer mislabels explain time as a “build”.
- Summary wording clarified to avoid interpretive claims:
- “Generated at (UTC)” replaces “Built at (UTC)” in summaries
- Capability mapping status now reported as
present: yes|no
explain --summaryoutput is now safe to paste into emails and reports.
- Aligned CLI, package, and build metadata versioning
- Hardened pre-release verification workflow (
verify-release.sh) - Clarified maintainer release checks vs smoke tests
- Improved repository hygiene and ignore rules
- No changes to course schema, validation behaviour, or governance logic
- This release focuses on reproducibility, auditability, and release confidence
- Structured AI scoping metadata (
ai_scoping) as a first-class, inspectable block incourse.yml- Separates narrative AI positioning from structural AI boundaries
- Designed for governance clarity, auditability, and policy interpretation
- AI scoping recorded in
manifest.json- Stored with:
- presence flag,
- stable SHA-256 hash,
- inspectable structure
- Enables deterministic detection of AI scope changes without inspecting content
- Stored with:
- SIG-AI-001 behaviour refined
- Advisory signal is now suppressed when valid
ai_scopingmetadata is present - Reduces false-positive governance noise in well-specified courses
- Advisory signal is now suppressed when valid
- Manifest schema version bumped to 1.4.0
- Adds first-class
signalsarray - Fully backward compatible for downstream consumers
- Adds first-class
- Schema alignment between
design_intent.ai_positionandai_scoping - Signal computation determinism under strict CI profiles
- Validation noise under strict governance profiles for well-scoped courses
- No new enforcement introduced
- No changes to build or render outputs
- Signals remain informational by default
- Fully backward compatible with v1.13.0 (except improved signal precision)
- This is a stabilisation and governance-hardening patch
- Intended to make v1.13 safe for institutional rollout and CI use
-
Absence signalling framework
- The engine now computes explicit, deterministic signals for missing or thin declarations, including:
- missing design intent,
- declared alignment without inspectable mapping,
- thin or empty capability mappings,
- AI positioning without structural scoping
- Signals are:
- non-blocking by default,
- recorded in
manifest.json, - interpreted only by policies (never enforced by the engine)
- The engine now computes explicit, deterministic signals for missing or thin declarations, including:
-
Signals recorded in
manifest.json- Provides a machine-readable governance surface
- Enables transparent downstream interpretation by QA tools, CI pipelines, and dashboards
- Clear separation of responsibilities
- Engine computes facts
- Policies interpret signals
- Institutions decide enforcement thresholds
- Validation behaviour clarified to reduce ambiguity and over-warning
- Signals are informational unless elevated by policy
- No automatic enforcement or scoring introduced
- No pedagogical judgement performed
- Fully backward compatible with v1.12.0
- This release completes the governance contract introduced in earlier versions
- Establishes a stable foundation for institutional adoption
-
Design intent metadata block (
design_intent) incourse.yml- Optional, informational author-declared rationale
- Intended to capture:
- design context and reasoning,
- AI positioning and boundaries,
- relevant frameworks or governance considerations
- Does not affect build, render, validation, or enforcement behaviour
-
Design intent recorded in
manifest.json- Stored with:
- presence flag,
- stable SHA-256 hash,
- human-readable summary
- Enables auditability and change detection without inspecting lesson content
- Stored with:
-
Explain output enhanced
course-engine explainnow surfaces design intent in:- machine-readable JSON output
- human-readable text reports
- Available in artefact (manifest-backed) explain mode
- Manifest schema version bumped to 1.3.0
- Adds
design_intentmetadata - Fully backward compatible with earlier manifests
- Adds
- No changes to build outputs or rendering behaviour
- No new validation or enforcement logic introduced
- Design intent is purely informational
- Fully backward compatible with v1.11.0
- This release strengthens governance transparency and audit readiness
- Design intent complements (but does not replace)
framework_alignmentandcapability_mapping
- Demonstration course updated to include defensible capability mapping
- Declares both
framework_alignment(intent) andcapability_mapping(coverage and evidence) - Enables end-to-end QA, validation, and reporting demonstrations
- Declares both
- Documented explainability JSON contract for policy resolution
- Formalises the structure and guarantees of
validate --explain --json - Intended for CI pipelines, dashboards, and governance tooling
- Formalises the structure and guarantees of
- Policy documentation clarified to emphasise:
- structural (not qualitative) validation
- requirement for
capability_mappingto enable validation - separation between declaration, reporting, and enforcement
- Documentation aligned with current CLI semantics and governance positioning
- No changes to build outputs, schemas, or validation logic
- No new enforcement behaviour introduced
- Fully backward compatible with v1.10.0
- This is a documentation and adoption release
- Intended to make existing governance features easier to understand and operationalise
- Introduced
--format json|textas the preferred output selector forcourse-engine explain - Retained
--jsonas a legacy / backward-compatibility flag - Clarified output precedence:
--formatalways overrides--json- JSON remains the default when no flags are supplied
- Improved CLI help text to explicitly document defaults and overrides
- Eliminated ambiguity in explain output selection for CI, QA, and automation workflows
- Hardened type safety across explain, policy, and exporter subsystems
- Achieved clean static analysis (
ruff,mypy) and test (pytest) runs across the codebase
- No changes to build outputs, schemas, or enforcement behaviour
- Explain output remains deterministic except for runtime timestamps
- Fully backward compatible with existing scripts using
--json
- This is a polish and interface-hardening release
- Explainability is now considered stable and governance-ready
- Internal refactoring and groundwork for explain interface stabilisation
- No user-facing feature additions
- No schema, build, or behaviour changes
- Released as a stepping stone toward v1.10.0
- Explain now resolves lesson-level
source:files and reports full provenance undersources.filesandsources.resolution. - File existence, byte size, and SHA-256 hashes are surfaced for governance and audit workflows.
- This is an explain-only change.
- No impact on build, render, or UI output.
- Includes a demo regression fixture to validate provenance resolution.
- Corrected engine version reporting to derive from installed package metadata (eliminates version drift in CLI and explain JSON).
- Lesson pages now use in-body table of contents (TOC) for long-form readability
- Removed redundant “Quick links” section from lessons index
- Standardised lesson navigation labels using
lesson_nav_title - Improved previous/next lesson navigation placement for clearer progression
- This release focuses on UI/UX improvements only
- No changes to course schema or build logic
- Native support for external lesson source files via
lesson.source- Lessons can now be authored as standalone Markdown (
.md) or Quarto (.qmd) files - Source files are resolved relative to
course.yml - Lesson titles are inferred automatically from the first Markdown H1 (
# Heading) if omitted
- Lessons can now be authored as standalone Markdown (
- Lesson source provenance tracking in
manifest.json- Records declared source path, resolved absolute path, and SHA-256 hash
- Enables auditability, reproducibility, and change detection
- Fail-fast guardrails for common authoring errors
- Clear errors for unsupported top-level keys (
content:, top-levelmodules:) - Explicit validation when both
sourceandcontent_blocksare defined - Explicit validation when neither
sourcenorcontent_blocksis defined
- Clear errors for unsupported top-level keys (
- Manifest schema version bumped to 1.2.0
- Adds
lesson_sourcessummary metadata
- Adds
- External lesson sourcing is fully deterministic
- Lesson content is embedded at build time
- Build output does not depend on runtime file availability
- Backwards compatible with inline
content_blocks - No change to validation, policy, or reporting behaviour unless lesson sources are used
- This release eliminates the previous “silent empty lessons” failure mode
- External lesson files are treated as inputs, not build artefacts
- This lays the foundation for future framework packs and institutional portability (v1.7+)
- Explain-only policy resolution mode (
course-engine validate --explain) - Machine-readable JSON output for policy resolution (
--explain --json) - Policy provenance surfaced in explain output:
policy_idpolicy_nameownerlast_updated
- Support for explain mode without requiring
manifest.json - Preset and file-based policy support in explain mode
- Explain mode does not execute validation
- No build artefacts are required
- Backwards compatible with v1.4 validation behaviour
- Enables safe integration with CI pipelines, dashboards, and external governance tooling
- Explain JSON output is considered a contract-stable interface
- Policy-based validation framework
- Support for preset and file-based policy definitions
- Profile inheritance and resolution logic
- This release primarily introduced internal policy infrastructure
- User-facing explain and JSON interfaces were finalised in v1.5.0
- Improved
course-engine validateoutput wording for clarity (non-strict vs strict)
- Capability mapping defensibility validation (
course-engine validate) - Rule-based validation engine operating on
manifest.json - Non-strict (default) and strict validation modes
- Machine-readable exit codes for QA / CI workflows
- Validation does not modify builds or enforce frameworks
- Builds remain non-blocking unless strict validation is explicitly enabled
- Capability coverage report command (
course-engine report) - Text, verbose, and JSON report outputs
- Optional
--fail-on-gapsexit code for QA / CI use
- Capability mapping remains informational (not enforced)
- Optional top-level
capability_mappingmetadata incourse.yml - Capability mapping recorded in
manifest.json(informational, not enforced) course-engine inspectshows a capability mapping summary- Tests covering parsing and manifest inclusion
- Repository hygiene: ignore packaging/build artefacts (e.g.
*.egg-info/)
- Initial stable release
- Deterministic build pipeline from
course.yml - Multi-format outputs:
- Multi-page Quarto website
- Single-page HTML handout
- Print-ready PDF (Quarto + TinyTeX)
- Markdown export package
- Non-destructive builds by default (
--overwriterequired) - Build auditability via
manifest.json - CLI commands:
init,build,render,inspect,clean,check - End-user documentation and CI workflow added