Skip to content

Modernization roadmap

This page summarizes the modernization design that produced this documentation site and the run / doctor / tutorial / namelist additions. The full dossier — including the persona-validated reviews — lives in the repository under docs/modernization/.

nwp-compose is technically mature, but a persistent last-mile gap stands between “I have a workflow.yaml” and “my forecast is cycling”: the path is multi-step, assumes Cylc fluency, and several checks fail silently. The project’s own persona reviews surfaced the same five themes across every phase:

  1. cylc validate passing ≠ runnable;
  2. warnings that emit but don’t block;
  3. docs that drift from code;
  4. the gap between generate and “ready to run” (with <workflow_id> undefined);
  5. demo/banner copy overstating capability.

A scientist migrating off a personal bash/cron setup hits themes 1, 4, and 5 on their first afternoon. So the design’s spine is one sentence: lower the Cylc-fluency barrier and make the last mile a guided, honest, gated, single-command experience — without elevation, on any shared system.

  • Unprivileged-everywhere — no sudo, no system services, no Docker daemon; $XDG-aware, redirectable state; rootless containers; user crontab.
  • Additive only — the v0 schema is frozen; everything is a new command, doc, or optional parameter. The freeze test stays green.
  • Honor code-gen resistance — shell out to Cylc, drive the existing namelist/render primitives; no Python flow_builder.
  • Generate docs from code — the CLI reference is introspected from the live Click app, so a drifted doc is a failing build, not a stale page.
  • Gate, don’t just warn — every new path that produces a runnable artifact routes through the same validate/unphysical-block gate.

Ranked, each unprivileged-aware (no recommendation requires elevation):

# Recommendation Why Effort
1 Commit a dependency lockfile (uv.lock) cylc-flow’s 30+ transitive deps are unpinned today — the highest-value supply-chain win. low
2 Vite build for gui/app/ Retires the ~1.5 MB in-browser Babel transpile and the dev-build React; enables tree-shaking and production builds. Runs entirely as the developer’s user. medium
3 SRI on every CDN load The Pyodide and reveal.js loads lack integrity hashes; add them or self-host. low
4 CSP at the Caddy edge Defense-in-depth beyond tag-level SRI for the hosted GUI. low
5 Rootless container recipes Apptainer/Podman defs so the CI harness and any container path run without a Docker daemon on HPC. medium
6 XDG-aware state paths XDG_CACHE_HOME/XDG_DATA_HOME/CYLC_RUN_DIR honored everywhere (see the unprivileged checklist). low

Following the repository’s sci-plan → sci-review / eng-plan → eng-review convention, the design was validated by two adversarial personas — a senior scientist/modeler and a senior research software engineer. Their reviews (in docs/modernization/51-sci-review.md and 52-eng-review.md) caught real correctness bugs in the draft specs — e.g. that MPAS CFL is the non-blocking W5, not a blocking code, and that several components declare namelist templates that are not shipped — which were folded back into these docs. That is the review loop working as intended.