From 13cb5f3fd33ade25e4fb8a0134de0bcd56fd6bd8 Mon Sep 17 00:00:00 2001 From: Tapio Schneider Date: Tue, 14 Jul 2026 11:22:46 -0700 Subject: [PATCH 1/3] Squashed 'docs/dev-guides/' content from commit ef62c6321 git-subtree-dir: docs/dev-guides git-subtree-split: ef62c6321577e61887182651f2ffbe1b63e1b3a1 --- AGENTS.md | 65 ++++ LICENSE | 201 +++++++++++++ README.md | 153 ++++++++++ architecture/architectural_boundaries.md | 68 +++++ architecture/cross_repo_contracts.md | 50 ++++ architecture/dependency_management.md | 127 ++++++++ architecture/ecosystem_conventions.md | 109 +++++++ architecture/repo_structure.md | 46 +++ code-quality/changelogs_and_versions.md | 167 +++++++++++ code-quality/code_style.md | 166 +++++++++++ code-quality/documentation_policy.md | 342 ++++++++++++++++++++++ code-quality/getting_started.md | 38 +++ code-quality/glossary.md | 30 ++ code-quality/software_design_patterns.md | 340 +++++++++++++++++++++ code-quality/variable_list.md | 108 +++++++ infrastructure/clima_comms.md | 124 ++++++++ infrastructure/testing_and_validation.md | 213 ++++++++++++++ performance/ad_compatibility.md | 76 +++++ performance/allocation_debugging.md | 126 ++++++++ performance/branchless_code.md | 231 +++++++++++++++ performance/gpu_performance.md | 212 ++++++++++++++ performance/numerical_robustness.md | 90 ++++++ performance/type_stability.md | 122 ++++++++ templates/AGENTS.md.template | 28 ++ templates/repo_specific_guide.md.template | 41 +++ templates/update_dev_guides.yml.template | 97 ++++++ workflow/agent_autonomy.md | 66 +++++ workflow/ci_triage.md | 82 ++++++ workflow/cross_repo_issue_pr_search.md | 60 ++++ workflow/debugging.md | 105 +++++++ workflow/onboarding.md | 149 ++++++++++ workflow/review.md | 115 ++++++++ workflow/running_on_gpu.md | 90 ++++++ 33 files changed, 4037 insertions(+) create mode 100644 AGENTS.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 architecture/architectural_boundaries.md create mode 100644 architecture/cross_repo_contracts.md create mode 100644 architecture/dependency_management.md create mode 100644 architecture/ecosystem_conventions.md create mode 100644 architecture/repo_structure.md create mode 100644 code-quality/changelogs_and_versions.md create mode 100644 code-quality/code_style.md create mode 100644 code-quality/documentation_policy.md create mode 100644 code-quality/getting_started.md create mode 100644 code-quality/glossary.md create mode 100644 code-quality/software_design_patterns.md create mode 100644 code-quality/variable_list.md create mode 100644 infrastructure/clima_comms.md create mode 100644 infrastructure/testing_and_validation.md create mode 100644 performance/ad_compatibility.md create mode 100644 performance/allocation_debugging.md create mode 100644 performance/branchless_code.md create mode 100644 performance/gpu_performance.md create mode 100644 performance/numerical_robustness.md create mode 100644 performance/type_stability.md create mode 100644 templates/AGENTS.md.template create mode 100644 templates/repo_specific_guide.md.template create mode 100644 templates/update_dev_guides.yml.template create mode 100644 workflow/agent_autonomy.md create mode 100644 workflow/ci_triage.md create mode 100644 workflow/cross_repo_issue_pr_search.md create mode 100644 workflow/debugging.md create mode 100644 workflow/onboarding.md create mode 100644 workflow/review.md create mode 100644 workflow/running_on_gpu.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..1e28dd60c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,65 @@ +# CliMA Developer Guides: Agent Entry Point + +Read this file first. It is the agent entry point for the shared engineering guidelines. Each guide applies across the CliMA ecosystem unless stated otherwise. + +In consumer repos, these guides live at `docs/dev-guides/` and are supplied by a git subtree from the canonical source . The consumer's root `AGENTS.md` references this file and the repo-specific guide. Edit shared guides in the canonical repo, not in the subtree copy. + +## Before you act: agent autonomy + +Local, reversible work (editing files, running tests, formatting, committing to the current branch) needs no permission. Get explicit user approval before any irreversible, externally visible, or scientifically consequential action: + +- **Git/GitHub**: `git push`, force-push, rebasing or amending pushed commits, `git reset --hard` or `git clean` with uncommitted changes, deleting branches, opening/merging/closing PRs, commenting on issues or PRs, tagging or pushing releases. +- **Versioning and dependencies**: bumping `version` in `Project.toml`, editing `Manifest.toml`, changing `[compat]` or `[deps]`, `Pkg.update()`. +- **Reproducibility data**: editing reference counters, MSE tolerances, or checksum/golden files in reproducibility-test directories. Change these only for a user-confirmed output change. +- **CI and infrastructure**: editing `.buildkite/pipeline.yml` or `.github/workflows/*`, adding or removing CI jobs, disabling tests, skipping hooks (`--no-verify`). +- **Public API and user-visible behavior**: renaming or removing exported symbols, renaming diagnostics or changing their units, changing or removing user-visible config keys. + +The full enumeration and the allowed-without-approval list are in [workflow/agent_autonomy.md](workflow/agent_autonomy.md). When in doubt, ask. + +## Guides + +### Architecture + +- [repo_structure.md](architecture/repo_structure.md): how to navigate any CliMA Julia package. +- [ecosystem_conventions.md](architecture/ecosystem_conventions.md): module aliases, `Y`/`Yₜ`/`p` state layout, `ᶜ`/`ᶠ` notation, CI structure, reproducibility, diagnostics. +- [architectural_boundaries.md](architecture/architectural_boundaries.md): layered architecture and boundary rules. +- [cross_repo_contracts.md](architecture/cross_repo_contracts.md): call-site conventions for ecosystem packages. +- [dependency_management.md](architecture/dependency_management.md): runtime vs dev dependencies, compat bounds. + +### Performance + +- [gpu_performance.md](performance/gpu_performance.md): GPU kernel rules, broadcast patterns, allocation avoidance. +- [branchless_code.md](performance/branchless_code.md): avoiding warp divergence with `ifelse`, evaluate-both-cases splits, and fixed-iteration solvers chosen by offline tests. +- [type_stability.md](performance/type_stability.md): Float32 compatibility, inference checks, struct field rules. +- [numerical_robustness.md](performance/numerical_robustness.md): denominator regularization, clamping, NaN/Inf avoidance. +- [ad_compatibility.md](performance/ad_compatibility.md): AD-safe patterns for ForwardDiff and Enzyme. +- [allocation_debugging.md](performance/allocation_debugging.md): locating heap allocations with `Profile.Allocs`, JET, `@code_warntype`, flame graphs. + +### Code Quality + +- [getting_started.md](code-quality/getting_started.md): orienting newcomers to writing pointwise code compatible with ClimaCore `Field`s and broadcasting. +- [code_style.md](code-quality/code_style.md): formatting, variable locality, Git workflow, feature removal, naming conventions. +- [documentation_policy.md](code-quality/documentation_policy.md): docstrings, repository-level docs, minimally viable documentation. +- [changelogs_and_versions.md](code-quality/changelogs_and_versions.md): `NEWS.md` format, SemVer rules, and the release/tagging flow. +- [variable_list.md](code-quality/variable_list.md): standardized CliMA variable naming conventions. +- [glossary.md](code-quality/glossary.md): general CliMA software and simulation terminology. +- [software_design_patterns.md](code-quality/software_design_patterns.md): numbered SDPs for branchless logic, functors, parameter extraction, and more. + +### Infrastructure + +- [testing_and_validation.md](infrastructure/testing_and_validation.md): type-stability checks, Aqua.jl, allocation regression, AD tests. +- [clima_comms.md](infrastructure/clima_comms.md): device-agnostic and MPI-distributed code patterns. + +### Workflow + +- [onboarding.md](workflow/onboarding.md): install Julia, clone a CliMA repo, set up Revise/Infiltrator/JuliaFormatter, first PR loop. +- [running_on_gpu.md](workflow/running_on_gpu.md): run a model on GPU — install Julia, add `CUDA.jl`, CUDA runtime compatibility, `CLIMACOMMS_DEVICE`, verify the device. +- [agent_autonomy.md](workflow/agent_autonomy.md): actions that require explicit user approval. +- [debugging.md](workflow/debugging.md): interactive debugging recipes for numerical instabilities, dispatch, and `Field` plotting. +- [review.md](workflow/review.md): PR review instructions and checklist. +- [ci_triage.md](workflow/ci_triage.md): checklist for "passes locally, fails on CI" failure modes. +- [cross_repo_issue_pr_search.md](workflow/cross_repo_issue_pr_search.md): org-scoped GitHub search to find and filter issues/PRs across CliMA. + +## Self-correction + +If this index is stale or missing a guide, update it here and in the matching [README.md](README.md#guides) overview. diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 000000000..d52e612ca --- /dev/null +++ b/README.md @@ -0,0 +1,153 @@ +# DeveloperGuides + +Shared engineering standards, architectural patterns, and development guidelines for human and AI developers across the [CliMA](https://clima.caltech.edu) ecosystem. + +## Guides + +Every guide applies across the CliMA ecosystem unless it says otherwise. + +### Architecture + +- [repo_structure.md](architecture/repo_structure.md): how to navigate any CliMA Julia package. +- [ecosystem_conventions.md](architecture/ecosystem_conventions.md): module aliases, `Y`/`Yₜ`/`p` state layout, `ᶜ`/`ᶠ` notation, CI structure, reproducibility, diagnostics. +- [architectural_boundaries.md](architecture/architectural_boundaries.md): layered architecture and boundary rules. +- [cross_repo_contracts.md](architecture/cross_repo_contracts.md): call-site conventions for ecosystem packages. +- [dependency_management.md](architecture/dependency_management.md): runtime vs dev dependencies, compat bounds. + +### Performance + +- [gpu_performance.md](performance/gpu_performance.md): GPU kernel rules, broadcast patterns, allocation avoidance. +- [branchless_code.md](performance/branchless_code.md): avoiding warp divergence with `ifelse`, evaluate-both-cases splits, and fixed-iteration solvers chosen by offline tests. +- [type_stability.md](performance/type_stability.md): Float32 compatibility, inference checks, struct field rules. +- [numerical_robustness.md](performance/numerical_robustness.md): denominator regularization, clamping, NaN/Inf avoidance. +- [ad_compatibility.md](performance/ad_compatibility.md): AD-safe patterns for ForwardDiff and Enzyme. +- [allocation_debugging.md](performance/allocation_debugging.md): locating heap allocations with `Profile.Allocs`, JET, `@code_warntype`, flame graphs. + +### Code Quality + +- [getting_started.md](code-quality/getting_started.md): orienting newcomers to writing pointwise code compatible with ClimaCore `Field`s and broadcasting. +- [code_style.md](code-quality/code_style.md): formatting, variable locality, Git workflow, feature removal, naming conventions. +- [documentation_policy.md](code-quality/documentation_policy.md): docstrings, repository-level docs, minimally viable documentation. +- [changelogs_and_versions.md](code-quality/changelogs_and_versions.md): `NEWS.md` format, SemVer rules, and the release/tagging flow. +- [variable_list.md](code-quality/variable_list.md): standardized CliMA variable naming conventions. +- [glossary.md](code-quality/glossary.md): general CliMA software and simulation terminology. +- [software_design_patterns.md](code-quality/software_design_patterns.md): numbered SDPs for branchless logic, functors, parameter extraction, and more. + +### Infrastructure + +- [testing_and_validation.md](infrastructure/testing_and_validation.md): type-stability checks, Aqua.jl, allocation regression, AD tests. +- [clima_comms.md](infrastructure/clima_comms.md): device-agnostic and MPI-distributed code patterns. + +### Workflow + +- [onboarding.md](workflow/onboarding.md): install Julia, clone a CliMA repo, set up Revise/Infiltrator/JuliaFormatter, first PR loop. +- [running_on_gpu.md](workflow/running_on_gpu.md): run a model on GPU — install Julia, add `CUDA.jl`, CUDA runtime compatibility, `CLIMACOMMS_DEVICE`, verify the device. +- [agent_autonomy.md](workflow/agent_autonomy.md): actions that require explicit user approval. +- [debugging.md](workflow/debugging.md): interactive debugging recipes for numerical instabilities, dispatch, and `Field` plotting. +- [review.md](workflow/review.md): PR review instructions and checklist. +- [ci_triage.md](workflow/ci_triage.md): checklist for "passes locally, fails on CI" failure modes. +- [cross_repo_issue_pr_search.md](workflow/cross_repo_issue_pr_search.md): org-scoped GitHub search to find and filter issues/PRs across CliMA. + +--- + +## About DeveloperGuides + +These guides are maintained in [CliMA/DeveloperGuides](https://github.com/CliMA/DeveloperGuides) and vendored into consumer repos as a Git subtree at the standardized path `docs/dev-guides/`. The material below is for maintaining and consuming that subtree; readers looking for engineering guidance want the [Guides](#guides) overview above. + +### Using the guides in a consumer repo + +A consumer repo keeps its own `AGENTS.md` at the root, which references `docs/dev-guides/AGENTS.md` (the agent entry point) plus a repo-specific guide (e.g. `docs/clima_atmos_specific.md`). See [`templates/`](templates/) for ready-to-copy starter files: a root `AGENTS.md`, a repo-specific guide skeleton, and the monthly sync workflow. + +```bash +# Add the subtree to a new consumer repo +git subtree add --prefix docs/dev-guides \ + https://github.com/CliMA/DeveloperGuides.git main --squash + +# Pull the latest guides manually (most repos automate this monthly via update_dev_guides.yml) +git subtree pull --prefix docs/dev-guides \ + https://github.com/CliMA/DeveloperGuides.git main --squash \ + -m "chore: sync dev guides from central repo" +``` + +> [!NOTE] +> **Subtree pitfalls.** +> +> - `git subtree add --prefix docs/dev-guides ...` nests all of DeveloperGuides, including its own `AGENTS.md`, `LICENSE`, and `README.md`, under that prefix. It does not touch the consumer's root files, so the initial add does not conflict with them. +> - The real risk is editing the vendored copy under `docs/dev-guides/` directly instead of upstream (see "Contributing" below). A later `git subtree pull` merges upstream changes into that path, so a local edit there can produce a genuine merge conflict. Resolve it like any merge conflict: fix the conflicting file, `git add`, `git commit`. Subtree operations use merge, not rebase, so `git rebase --continue` does not apply. +> - When there are no new upstream commits the monthly run is a clean no-op. The workflow now fails loudly on a genuine `git subtree pull` error instead of masking it, so a red run means something actually needs attention. + +### Fixing a broken subtree sync + +The monthly sync breaks in one of two ways: a dev-guides PR was squash-merged — which discards the `git subtree` metadata the next pull relies on — or the workflow lacks the write permissions it needs to open a PR. If a repo's sync stopped producing PRs, apply whichever fix below it needs; most repos only need the first. + +**1. Update the workflow file (do this on every consumer repo).** Replace the old workflow with the current template rather than hand-editing it: + +```bash +git checkout -b update-dev-guides-workflow +mkdir -p .github/workflows +curl -fsSL https://raw.githubusercontent.com/CliMA/DeveloperGuides/main/templates/update_dev_guides.yml.template \ + -o .github/workflows/update_dev_guides.yml +git add .github/workflows/update_dev_guides.yml +git commit -m "ci: refresh dev-guides sync workflow from template" +git push -u origin update-dev-guides-workflow +``` + +Then open a PR for that branch and merge it normally — this PR does not touch the subtree, so squash is fine. Also make sure **Settings → Actions → General → "Allow GitHub Actions to create and approve pull requests"** is enabled, or the workflow will fail when it tries to open the monthly sync PR. + +**2. Repair broken subtree metadata (only if a sync PR was ever squash-merged).** Symptom: a manual `git subtree pull` (or the workflow log) fails with `fatal: can't squash-merge: 'docs/dev-guides' was never added.` Remove and re-add the subtree: + +```bash +git checkout -b fix-dev-guides-subtree +git rm -r docs/dev-guides +git commit -m "chore: remove dev-guides subtree (re-adding to fix metadata)" +git subtree add --prefix docs/dev-guides \ + https://github.com/CliMA/DeveloperGuides.git main --squash +``` + +Open a PR for this branch and **merge it with a merge commit, not squash** — squash-merging here immediately re-breaks the metadata. Any local edits to files under `docs/dev-guides/` are discarded, which is correct: that copy is vendored and should only be changed upstream. + +### Contributing + +Edits to shared guidelines belong in [CliMA/DeveloperGuides](https://github.com/CliMA/DeveloperGuides), not in the vendored copy inside a consumer repo. Open PRs there; once merged, the next subtree pull propagates them to every consumer. + +- Each guide has a **Self-correction** section: if you discover a guide is stale or missing a pattern, update it directly. +- New guides go in the appropriate category directory and are added to this overview and to [AGENTS.md](AGENTS.md). +- Cross-references between guides use relative paths (e.g. `../performance/gpu_performance.md`). + +### Repository layout + +```text +├── AGENTS.md # Agent entry point: autonomy gate + guide index +├── README.md # This file: guide overview + repo info +├── architecture/ # System design, layering, contracts +├── performance/ # GPU, type stability, numerics, AD +├── code-quality/ # Style, docstrings, changelogs, naming +├── infrastructure/ # Testing, device abstraction +├── workflow/ # Onboarding, debugging, review, CI triage +└── templates/ # Starter files for consumer repos +``` + +### CliMA ecosystem + +These guides are the central source of engineering standards across [CliMA](https://github.com/CliMA), including: + +- [ClimaAtmos](https://github.com/CliMA/ClimaAtmos.jl) +- [ClimaCore](https://github.com/CliMA/ClimaCore.jl) +- [ClimaLand](https://github.com/CliMA/ClimaLand.jl) +- [ClimaOcean](https://github.com/CliMA/ClimaOcean.jl) +- [ClimaCoupler](https://github.com/CliMA/ClimaCoupler.jl) +- [Thermodynamics](https://github.com/CliMA/Thermodynamics.jl) +- [CloudMicrophysics](https://github.com/CliMA/CloudMicrophysics.jl) +- [SurfaceFluxes](https://github.com/CliMA/SurfaceFluxes.jl) +- [ClimaTimeSteppers](https://github.com/CliMA/ClimaTimeSteppers.jl) + +### License + +[![license][license-img]][license-url] Apache 2.0; see [LICENSE](LICENSE). + +[license-img]: https://img.shields.io/github/license/CliMA/DeveloperGuides +[license-url]: https://github.com/CliMA/DeveloperGuides/blob/main/LICENSE + +### Getting help + +For questions or suggestions, open an issue on [GitHub](https://github.com/CliMA/DeveloperGuides/issues). diff --git a/architecture/architectural_boundaries.md b/architecture/architectural_boundaries.md new file mode 100644 index 000000000..e9bf67bc9 --- /dev/null +++ b/architecture/architectural_boundaries.md @@ -0,0 +1,68 @@ +# Architectural Boundaries + +This guide defines the layered architecture used across CliMA model repositories and the rules that keep boundaries clean. Each repo's `*_specific.md` (linked from [AGENTS.md](../AGENTS.md)) maps these layers to its concrete directories. + +## 1. Layer hierarchy + +CliMA packages form a directed acyclic dependency graph. The canonical layering is: + +| Layer | Packages | Role | +| :---- | :------- | :--- | +| L0 | [ClimaParams.jl](https://github.com/CliMA/ClimaParams.jl), [RootSolvers.jl](https://github.com/CliMA/RootSolvers.jl), [UnrolledUtilities.jl](https://github.com/CliMA/UnrolledUtilities.jl), [LazyBroadcast.jl](https://github.com/CliMA/LazyBroadcast.jl), [MultiBroadcastFusion.jl](https://github.com/CliMA/MultiBroadcastFusion.jl), [EnsembleKalmanProcesses.jl](https://github.com/CliMA/EnsembleKalmanProcesses.jl), [NullBroadcasts.jl](https://github.com/CliMA/NullBroadcasts.jl), [RandomFeatures.jl](https://github.com/CliMA/RandomFeatures.jl) | Physical constants, calibratable parameters, generic math, and generic Julia utilities. No CliMA-internal dependencies. | +| L1 | [ClimaComms.jl](https://github.com/CliMA/ClimaComms.jl), [ClimaCore.jl](https://github.com/CliMA/ClimaCore.jl), [Thermodynamics.jl](https://github.com/CliMA/Thermodynamics.jl), [CubedSphere.jl](https://github.com/CliMA/CubedSphere.jl), [ClimaAnalysis.jl](https://github.com/CliMA/ClimaAnalysis.jl), [ClimaUtilities.jl](https://github.com/CliMA/ClimaUtilities.jl), [ClimaInterpolations.jl](https://github.com/CliMA/ClimaInterpolations.jl), [SeawaterPolynomials.jl](https://github.com/CliMA/SeawaterPolynomials.jl), [ClimaDiagnostics.jl](https://github.com/CliMA/ClimaDiagnostics.jl) | Foundations: device abstraction + MPI, fields & discretization, thermodynamic primitives, shared software tooling | +| L2 | [ClimaTimeSteppers.jl](https://github.com/CliMA/ClimaTimeSteppers.jl), [CloudMicrophysics.jl](https://github.com/CliMA/CloudMicrophysics.jl), [SurfaceFluxes.jl](https://github.com/CliMA/SurfaceFluxes.jl), [Insolation.jl](https://github.com/CliMA/Insolation.jl), [RRTMGP.jl](https://github.com/CliMA/RRTMGP.jl), [AtmosphericProfilesLibrary.jl](https://github.com/CliMA/AtmosphericProfilesLibrary.jl), [Oceananigans.jl](https://github.com/CliMA/Oceananigans.jl) | Higher-level libraries built on L1: time integration and physics parameterisations. | +| L3 | [ClimaAtmos.jl](https://github.com/CliMA/ClimaAtmos.jl), [ClimaLand.jl](https://github.com/CliMA/ClimaLand.jl), [ClimaOcean.jl](https://github.com/CliMA/ClimaOcean.jl), [CalibrateEmulateSample.jl](https://github.com/CliMA/CalibrateEmulateSample.jl), [ClimaSeaIce.jl](https://github.com/CliMA/ClimaSeaIce.jl), [ClimaOcean.jl](https://github.com/CliMA/ClimaOcean.jl) | Model repos: compose L1 / L2 to integrate state variables. | +| L4 | [ClimaCoupler.jl](https://github.com/CliMA/ClimaCoupler.jl), [ClimaCalibrate.jl](https://github.com/CliMA/ClimaCalibrate.jl) | Couples multiple L3 models, toolkit for calibration pipelines | + +**The rule**: a package at layer N may depend on packages at layers ≤ N, but never on packages at layers > N. Concretely: + +- Physics libraries (Thermodynamics, CloudMicrophysics, SurfaceFluxes) must not depend on ClimaCore, grid types, or any model repo. +- Infrastructure libraries (ClimaCore, ClimaComms, ClimaTimeSteppers) must not depend on physics libraries or model repos. +- Model repos must not depend on ClimaCoupler. + +Verify against actual dependencies with `Pkg.dependencies` if in doubt. A new dependency that creates an upward edge in this DAG is a design smell. + +### Role of each layer + +- **Physics libraries** (Thermodynamics.jl, CloudMicrophysics.jl, SurfaceFluxes.jl): public functions accept scalars or tuples and return scalars or `NamedTuple`s. They must not allocate `Array` or `Field` objects internally. +- **Infrastructure libraries** (ClimaCore.jl, ClimaTimeSteppers.jl, ClimaComms.jl): own the data structures, discretization, and parallelism. They define the types that model repos compose. +- **Parameter library** ([ClimaParams.jl](https://github.com/CliMA/ClimaParams.jl)): the central source of truth for physical constants and adjustable parameters that may be calibrated. All physics libraries read their constants from `ClimaParams`-derived parameter structs rather than hard-coding values. +- **Model repos** (ClimaAtmos.jl, ClimaLand.jl, ClimaOcean.jl, ClimaCoupler.jl): compose physics and infrastructure. Tendency functions call into physics libraries with extracted scalar values and write results back to fields via broadcasting. + +When adding new code, place it in the layer that owns the relevant concern. Do not embed broadcasting, field allocation, or IO inside physics functions, and do not re-implement numerical algorithms inside model-level tendency code. + +## 2. Parameter container design + +- Containers should be focused on the specific physical or mathematical domain they serve. +- Don't keep parameters "just in case." Fields added to a struct only to keep an old caller compiling (with no current user) accumulate as dead weight. When a refactor removes the last caller of a field, remove the field too. +- Keep parameter containers focused on physical constants and model parameters. Configuration flags, output options, and diagnostic metadata belong in the model's infrastructure layer, not in physics parameter structs. + +## 3. Avoid hidden field dependencies + +Do not access internal or undocumented fields of a sub-package's parameter struct directly (for example, `cm2p.internal_field`). Use the documented public accessor or the primary parameter source. + +This makes physics refactors in sub-packages safe without cascading breakage in the model. + +Bad: + +```julia +# Brittle: depends on the *internal* field names of a microphysics scheme +# struct that are not part of its documented API. +rain_terminal_velocity_coeff = cm1m_internal.rtv_coeff +``` + +Preferred: + +```julia +# Robust: access the documented public field of the unified terminal-velocity +# container (CloudMicrophysics.Parameters.TerminalVelocityParams). +rain_velocity_params = tv_params.chen2022.rain +``` + +## 4. Module import rules + +See [SDP 2](../code-quality/software_design_patterns.md) for the rule on cross-submodule imports inside `src/`. + +## Self-correction + +If this guide is discovered to be stale or missing a pattern, update it. diff --git a/architecture/cross_repo_contracts.md b/architecture/cross_repo_contracts.md new file mode 100644 index 000000000..b1ea950fa --- /dev/null +++ b/architecture/cross_repo_contracts.md @@ -0,0 +1,50 @@ +# Cross-Repo Contracts + +This guide documents the conventions for calling ecosystem packages from CliMA model repositories. Rules are at the call-site level; internal package APIs are not documented here. + +## General principle + +Always pass the package's *parameter container* (for example, `thermodynamics_params`, `surface_flux_params`) into physics functions rather than individual constants. This ensures consistency across model components and makes calibration transparent. + +## How to find the current API of a CliMA dependency + +You typically will not have the dependency's source checked out next to the model repo. Use this order: + +1. **`NEWS.md`** of the dependency, if accessible: it lists API changes per release. +2. **The dev'd path under `~/.julia/dev/.jl`**, if the user has the package dev'd locally. +3. **The package's `docs/src/`**, which usually documents the supported call surface. +4. **Existing call sites in this repo**: grep for the package's module alias in `src/` to see how it is already used. + +Treat anything not in the package's `docs/` as internal and unstable. + +## Thermodynamics.jl + +- Pass the thermodynamics parameter container (e.g. `p.params.thermodynamics_params` in ClimaAtmos) into thermodynamic functions; do not hard-code thermodynamic constants. +- The public API is fully functional and stateless: functions take a parameter container and the relevant scalar arguments directly. +- Many functions are dispatched on a *formulation type* that names the independent variables. The available formulations (subtypes of `IndepVars`) are `TD.ρe()`, `TD.pe()`, `TD.ph()`, `TD.pρ()`, `TD.pθ_li()`, `TD.ρθ_li()`. For example: `TD.air_temperature(thp, TD.ph(), h, q_tot, q_liq, q_ice)`. +- For iterative phase-equilibrium calculations inside GPU kernels, prefer the fixed-iteration `saturation_adjustment` variants (the GPU default is a 2-iteration Newton solve with no convergence flag) to avoid thread divergence. See [SDP 19](../code-quality/software_design_patterns.md) and the [Branchless Code Guide §4–5](../performance/branchless_code.md). + +## CloudMicrophysics.jl + +- The microphysics scheme is passed as a singleton type (e.g. `Microphysics0Moment()`, `Microphysics1Moment()`, `Microphysics2Moment()`); dispatch on it eliminates dead branches at compile time. +- The bulk-tendency wrappers (e.g. `bulk_microphysics_tendencies`) return `NamedTuple`s. Materialize them into a pre-allocated `NamedTuple`-of-`Field`s scratch slot in the cache and then issue one `@.` broadcast per target field. See the "Materialization" and "Multi-field updates" subsections in [GPU Performance Guide §3](../performance/gpu_performance.md). Process-rate primitives (e.g. `accretion`, `terminal_velocity`, `conv_q_icl_to_q_sno`) return scalars and can be broadcast directly. +- The terminal-velocity parameters live in a unified container `CMP.TerminalVelocityParams` with fields `stokes`, `chen2022`, `blk1m`. Use these documented fields rather than poking into internal scheme-specific structs. + +## SurfaceFluxes.jl + +- Pass a `SurfaceFluxes.Parameters.SurfaceFluxesParameters` container (the concrete subtype of `AbstractSurfaceFluxesParameters`); do not hard-code flux constants. +- Surface flux computation is expensive (root-finding on the Monin–Obukhov length); call it once per stage in the infrastructure layer, not inside tendency hot paths. +- Public entry points include `surface_fluxes` (the bulk solver), `sensible_heat_flux`, `latent_heat_flux`, and `compute_profile_value` (for recovering profile values at a given height). Round-trip tests against these are an idiomatic way to validate flux changes. See [testing_and_validation.md §2 Round-trip tests](../infrastructure/testing_and_validation.md#2-round-trip-inverse-tests). + +## ClimaParams.jl + +Extract the specific parameter sub-struct (e.g. `thp = p.params.thermodynamics_params`) to a local variable before any `@.` broadcast. Capturing the full `p.params` container can push a large struct into GPU kernel parameter memory and exceed hardware limits. See [SDP 20](../code-quality/software_design_patterns.md) for the rule, rationale, and worked example. + +## General cross-repo guidance + +- Before writing a new call site, check the target package's `NEWS.md` for recent API changes. +- Treat every function whose name ends in `_deprecated` or that is annotated `@deprecate` as absent; use the replacement. + +## Self-correction + +If this guide is discovered to be stale or missing a pattern, update it. diff --git a/architecture/dependency_management.md b/architecture/dependency_management.md new file mode 100644 index 000000000..caefc3504 --- /dev/null +++ b/architecture/dependency_management.md @@ -0,0 +1,127 @@ +# Dependency Management Guide + +This guide covers rules for managing Julia package dependencies in CliMA repositories. + +## 1. Multiple `Project.toml`s in one repo + +CliMA repos typically have several Julia environments side-by-side, each with its own `Project.toml` (and, if instantiated, `Manifest.toml`). They serve different purposes and must be kept distinct. + +| Path | What it is | Activated by | +|:------------------------------|:----------------------------------------------------------------------------------------------------------|:--------------------------------------------| +| `Project.toml` (repo root) | The package itself: runtime `[deps]`, `[compat]`, `[weakdeps]`, `[extensions]`. | `using Pkg; Pkg.activate(".")` | +| `test/Project.toml` | Test-only dependencies (Aqua, JET, BenchmarkTools, CUDA, Documenter, etc.). | `Pkg.test()` | +| `docs/Project.toml` | Documentation build dependencies (Documenter, Literate, plotting). | `julia --project=docs docs/make.jl` | +| `perf/Project.toml` | Allocation / flame / JET scripts (BenchmarkTools, Profile tools). | `julia --project=perf perf/