|
1 | 1 | # KomaMRI.jl |
2 | 2 |
|
3 | | -## Git |
4 | | -- Use a new branch for new features. Base it on `master`. |
5 | | -- Never push to `master`. |
6 | | -- If the current worktree has unrelated uncommitted changes and you need a clean branch, prefer a separate worktree instead of stashing or rewriting the user's changes. |
7 | | -- If the branch should start from the latest upstream `master`, fetch first and branch from `origin/master` rather than a potentially stale local `master`. |
8 | | -- Keep PRs scoped to one issue or feature when possible. |
| 3 | +## Style |
| 4 | +- Prioritize non-verbosity and information density. |
| 5 | +- Prioritize elegance and simplicity: concise idiomatic Julia, no abstract fields, no speculative abstractions. |
| 6 | +- Type function arguments only when dispatch needs them. |
| 7 | +- Prefer dispatch over `isa`/type-branching when behavior depends on type. |
| 8 | +- Use low-level constructors like `new{typeof(...)}` only in the minimal inner-constructor boundary that actually needs them. |
| 9 | +- Add helper functions only when reused or semantically justified. |
| 10 | +- Add docstrings only for public-facing functions. |
| 11 | +- Prefer clear names over explanatory comments. Add comments only when they add information. |
| 12 | +- Be terse. Assume expert user. |
| 13 | +- Prefer commands/diffs over long explanations. |
| 14 | +- Keep diffs tight. Do not reformat or clean up unrelated code. |
9 | 15 |
|
10 | | -## Repo Shape |
11 | | -- KomaMRI is a monorepo. The umbrella package lives at the repo root. |
12 | | -- Subpackages: `KomaMRIBase`, `KomaMRICore`, `KomaMRIFiles`, `KomaMRIPlots`. |
13 | | -- The root `KomaMRI` package directly depends on `KomaMRICore`, `KomaMRIFiles`, and `KomaMRIPlots`. |
14 | | -- `KomaMRICore`, `KomaMRIFiles`, and `KomaMRIPlots` depend on `KomaMRIBase`. |
15 | | -- Each package has its own `Project.toml`. Test envs live under `*/test/Project.toml`. Docs use `docs/Project.toml`. |
16 | | -- Do not edit `Manifest.toml` directly. Let `Pkg` own generated manifest state. |
17 | | -- `Manifest.toml` churn is usually not commit-worthy here. Manifests are mostly ignored in this repo, so do not commit manifest changes unless explicitly asked. |
| 16 | +## Git |
| 17 | +- If the user gives an existing branch/worktree, use it after verifying it is the intended one. |
| 18 | +- If starting feature/PR work yourself, create a unique branch from latest `origin/master` in a separate worktree; keep the main checkout on `master`. |
| 19 | +- If the active checkout is detached, create a unique local branch there before editing. |
| 20 | +- Fresh worktree pattern: `git fetch origin && git worktree prune && git worktree add -b codex/<task> ../KomaMRI.jl-<task> origin/master`. |
| 21 | +- If a branch/path exists, choose a new name. Do not force-remove unless asked. |
| 22 | +- Never push unless the latest user message explicitly asks. Never push to `master`. |
| 23 | +- No destructive Git commands without explicit approval. |
18 | 24 |
|
19 | | -## Julia Workflow |
20 | | -- Use idiomatic Julia, not Python habits. |
21 | | -- Treat the relevant project directory as the environment. Use `julia --project=<path>` and `Pkg.activate(...)`. |
22 | | -- Prefer project-local environments over the global default environment. |
23 | | -- Never accept Julia/Pkg interactive prompts that add `KomaMRIBase` to the root `Project.toml`. Abort the prompt and activate the correct project instead. |
24 | | -- Do not create alternate env roots, `env/` folders, or `DEPOT` / `HOME` hacks unless explicitly asked. |
25 | | -- Reuse a persistent Julia REPL with Revise. Do not start a fresh REPL for convenience, precompilation, or one-off commands. |
26 | | -- Only restart the REPL if none exists, it crashed, or the user asks. Say why first. |
27 | | -- Keep the REPL open until explicitly told to close it. |
28 | | -- Keep diffs tight. Do not reformat or "clean up" unrelated code. |
29 | | -- Read `Project.toml` when needed, but change dependencies and compat via `Pkg` APIs, not by hand-editing dependency state casually. |
| 25 | +## Repo |
| 26 | +- Monorepo packages: root `KomaMRI`, plus `KomaMRIBase`, `KomaMRICore`, `KomaMRIFiles`, `KomaMRIPlots`. |
| 27 | +- `KomaMRICore`, `KomaMRIFiles`, and `KomaMRIPlots` depend on `KomaMRIBase`; the root package depends on those three. |
| 28 | +- Each package has its own `Project.toml`; tests use `*/test/Project.toml`; docs use `docs/Project.toml`. |
| 29 | +- Root `[workspace]` includes `test`, `docs`, `benchmarks`, and all subpackages. |
| 30 | +- Do not edit `Manifest.toml` directly or commit manifest churn unless explicitly asked. |
30 | 31 |
|
31 | | -## Local Package Wiring |
32 | | -- This repo defines a root `[workspace]` with `test`, `docs`, `benchmarks`, `KomaMRIBase`, `KomaMRICore`, `KomaMRIFiles`, and `KomaMRIPlots`. |
33 | | -- On modern Julia/Pkg workspaces, prefer the workspace-first path instead of blindly `Pkg.develop`-ing every local subpackage: |
34 | | -```julia |
35 | | -using Pkg |
36 | | -Pkg.activate(".") |
37 | | -Pkg.instantiate() |
38 | | -``` |
39 | | -- If you want a child project active, activate that child directly; it still participates in the shared workspace manifest: |
40 | | -```julia |
41 | | -using Pkg |
42 | | -Pkg.activate("KomaMRICore") # or docs / benchmarks / another workspace child |
43 | | -Pkg.instantiate() |
44 | | -``` |
45 | | -- This also applies to docs: |
46 | | -```julia |
47 | | -using Pkg |
48 | | -Pkg.activate("docs") |
49 | | -Pkg.instantiate() |
50 | | -``` |
51 | | -- Use explicit `Pkg.develop(path=...)` only when you need path-tracked local packages outside the normal workspace flow, or when matching older/compatibility-oriented setup. |
52 | | -- If you need to mirror the current CI/docs wiring exactly, use the explicit path setup from `.github/workflows/CI.yml`, e.g. for docs: |
53 | | -```julia |
54 | | -using Pkg |
55 | | -Pkg.activate("docs") |
56 | | -Pkg.develop([ |
57 | | - PackageSpec(path=pwd(), subdir="."), |
58 | | - PackageSpec(path=pwd(), subdir="KomaMRIBase"), |
59 | | - PackageSpec(path=pwd(), subdir="KomaMRICore"), |
60 | | - PackageSpec(path=pwd(), subdir="KomaMRIFiles"), |
61 | | - PackageSpec(path=pwd(), subdir="KomaMRIPlots"), |
62 | | -]) |
63 | | -Pkg.instantiate() |
64 | | -``` |
65 | | -- CI still uses explicit `Pkg.develop(...)` wiring today because the matrix includes Julia `1.10`, so use that path when reproducing CI exactly. |
| 32 | +## Julia |
| 33 | +- Use the relevant project: `julia --project=<path>` and `Pkg.activate(...)`; never use the global env by accident. |
| 34 | +- Use one persistent Julia REPL/session with Revise for Julia work. Do not run `julia -e`, `julia script.jl`, or package tests in fresh shell processes while a REPL is available; send commands to the session. Use a fresh process only when isolation is required or the user asks. Restart only if absent/crashed or the user asks. Keep it open. |
| 35 | +- Prefer workspace setup: activate root or the child project and `Pkg.instantiate()`. Use explicit `Pkg.develop(path=...)` only to reproduce CI or older Julia 1.10 wiring. |
| 36 | +- Change dependencies/compat with Pkg APIs, not casual `Project.toml` edits. |
| 37 | +- For performance work: profile first, benchmark with interpolation, then optimize the actual hotspot. |
66 | 38 |
|
67 | | -## Julia Code |
68 | | -- Do not be verbose. Prefer the shortest clear correct Julia solution that matches the surrounding style. |
69 | | -- Prioritize elegance and concision. Do not lie or take shortcuts. |
70 | | -- Prefer the simplest correct design. Do not add helpers, wrappers, aliases, or abstractions unless they materially improve clarity, reuse, or dispatch. |
71 | | -- Avoid review-hostile churn: unnecessary boilerplate, defensive overengineering, speculative abstractions, and large refactors when a small local change is enough. |
72 | | -- Do not overtype function arguments; add method types only when dispatch needs them. |
73 | | -- Do not use abstract types in structs. |
74 | | -- Follow existing repo style and BlueStyle where it matches the surrounding code. |
75 | | -- Add comments or docstrings only when they carry real information. |
76 | | -- Watch type stability. Use `@code_warntype` when warranted. |
77 | | -- For performance work, profile first, then benchmark with interpolation, then optimize the actual hotspot. |
| 39 | +## Python |
| 40 | +- Use `uv` for reproducible Python environments. Do not use bare `pip`. |
78 | 41 |
|
79 | | -## Julia Testing |
80 | | -- Use the correct project context. Wrong env selection causes misleading failures. |
81 | | -- No need to open a new REPL for testing; use `Pkg.test`. |
82 | | -- Prefer `Pkg.test(...)` over directly running `test/runtests.jl`. Only run `runtests.jl` directly when debugging the test runner itself. |
83 | | -- Run the narrowest relevant tests first. If the change crosses package boundaries, test each affected package and then the umbrella package if needed. |
84 | | -- From the repo root, the usual entry points are: |
85 | | -```julia |
86 | | -import Pkg |
87 | | -Pkg.test("KomaMRIBase") |
88 | | -Pkg.test("KomaMRICore") |
89 | | -Pkg.test("KomaMRIFiles") |
90 | | -Pkg.test("KomaMRIPlots") |
91 | | -Pkg.test() # KomaMRI umbrella package |
92 | | -``` |
93 | | -- `Pkg.test()` at the repo root exercises the `KomaMRI` package, including UI-oriented paths. On headless Linux, mirror CI and use `xvfb-run` for `KomaMRIPlots` and root `KomaMRI` tests. |
94 | | -- `KomaMRICore` defaults to CPU via `KomaMRICore/test/Project.toml`. To change backend, set `[preferences.KomaMRICore].test_backend` to `CPU`, `CUDA`, `AMDGPU`, `Metal`, or `oneAPI`, or use `Pkg.test("KomaMRICore"; test_args=\`CUDA\`)`. |
95 | | -- To control CPU thread count for `KomaMRICore`, use `Pkg.test("KomaMRICore"; julia_args=\`--threads=4\`)`. |
96 | | -- GPU backend packages must already be available locally before running non-CPU `KomaMRICore` tests. `oneAPI` is experimental. |
97 | | -- Do not commit backend-specific GPU packages such as `CUDA`, `AMDGPU`, `Metal`, or `oneAPI` to shared test projects like `KomaMRICore/test/Project.toml`. Add them only in the backend-specific CI/local test command or a temporary environment. |
98 | | -- For small exploratory tests, use a temporary environment. For longer isolated tests, use a temp folder with an activated environment. Reuse the same REPL. |
99 | | -- If you add behavior, add or update tests in the owning package's `runtests.jl`. |
100 | | -- Use `@testitem` tags correctly: |
101 | | - - `KomaMRIBase`: `:base` |
102 | | - - `KomaMRICore`: `:core` plus exactly one of `:motion` or `:nomotion` |
103 | | - - `KomaMRIFiles`: `:files` |
104 | | - - `KomaMRIPlots`: `:plots` |
105 | | - - `KomaMRI`: `:koma` |
106 | | -- If the user asks for benchmarking, run benchmarks sequentially, never in parallel. |
107 | | -- If the user asks to test a PR implementation, add that version with `Pkg` using `url` / `rev`; do not hand-copy files. |
| 42 | +## Testing |
| 43 | +- In the persistent Julia session, run tests from the correct project with `Pkg.test(...)`; use the narrowest package first. |
| 44 | +- Usual package tests: `Pkg.test("KomaMRIBase")`, `Pkg.test("KomaMRICore")`, `Pkg.test("KomaMRIFiles")`, `Pkg.test("KomaMRIPlots")`, root `Pkg.test()`. |
| 45 | +- Root and `KomaMRIPlots` tests may need `xvfb-run` on headless Linux. |
| 46 | +- `KomaMRICore` backend tests use `test_args` (`CPU`, `CUDA`, `AMDGPU`, `Metal`, `oneAPI`) or test preferences; do not commit backend GPU deps to shared test projects. |
| 47 | +- Use `@testitem` tags: `:base`, `:files`, `:plots`, `:koma`, and for core `:core` plus exactly one of `:motion` or `:nomotion`. |
| 48 | +- If testing a PR implementation, add it with Pkg `url`/`rev`; do not hand-copy files. |
108 | 49 |
|
109 | 50 | ## Docs |
110 | | -- For docs changes, use the `docs` environment. |
111 | | -- KomaMRI docs use Documenter.jl, DocumenterVitepress, Literate.jl, and PlutoSliderServer. |
112 | | -- Treat the source files as canonical: edit the hand-written docs and the `lit-*.jl` / `pluto-*.jl` sources, not the generated tutorial artifacts. |
113 | | -- Keep `DocumenterVitepress.deploydocs(...)` in `docs/make.jl`; do not replace it with `Documenter.deploydocs(...)`. |
114 | | -- Run doctests with: |
115 | | -```bash |
116 | | -julia --project=docs -e 'using Documenter: doctest; using KomaMRI; doctest(KomaMRI)' |
117 | | -``` |
118 | | -- Build docs locally with: |
119 | | -```bash |
120 | | -julia --project=docs docs/make.jl |
121 | | -``` |
122 | | -- For faster local docs iteration, you can temporarily set `build_vitepress = false` in `docs/make.jl`, regenerate docs, and preview with: |
123 | | -```bash |
124 | | -julia --project=docs -e 'using DocumenterVitepress; DocumenterVitepress.dev_docs("docs/build")' |
125 | | -``` |
126 | | -- `dev_docs` expects the build directory path `docs/build`, not `docs/build/.documenter`. |
127 | | -- `dev_docs` does not rerun `makedocs` for you. After content changes, rerun `julia --project=docs docs/make.jl`. |
128 | | -- Restore the normal Vitepress build setting before committing. |
129 | | -- Do not commit files generated by `docs/make.jl`, `Literate.markdown/script/notebook`, or `PlutoSliderServer.export_directory` unless explicitly asked. |
130 | | -- In practice, generated docs artifacts to avoid committing include `docs/src/tutorial/*`, `docs/src/tutorial/pluto/**`, and generated tutorial/download assets under `docs/src/public/`. |
131 | | - |
132 | | -## PRs |
133 | | -- Base PRs on `master`. |
134 | | -- Run the relevant package tests before opening or updating the PR. |
135 | | -- Docs PRs can use the `documentation` label to trigger preview docs deployment (`docs/make.jl push_preview` in CI). |
136 | | -- GPU-sensitive PRs should get `run-gpu-ci` at PR creation when the first CI run matters. This is for `KomaMRICore/ext/`, kernels, or backend-specific changes. `oneAPI` is experimental and excluded from the default GPU CI and benchmark path. |
137 | | -- `pre-release` triggers Julia pre-release CI; use it only when intentionally checking upcoming Julia compatibility. |
138 | | -- Give reviewers the missing context: what changed, why, and what you tested. |
| 51 | +- Use the `docs` environment. |
| 52 | +- Edit source docs, `lit-*.jl`, and `pluto-*.jl`; do not edit generated tutorial artifacts. |
| 53 | +- In the persistent Julia session activated for `docs`, build with `include("docs/make.jl")`; doctest with `using Documenter: doctest; using KomaMRI; doctest(KomaMRI)`. |
| 54 | +- Keep `DocumenterVitepress.deploydocs(...)` in `docs/make.jl`. |
| 55 | +- Do not commit files generated by `docs/make.jl`, Literate, or PlutoSliderServer unless explicitly asked. |
139 | 56 |
|
140 | | -## Releases |
141 | | -- JuliaRegistrator release notes must explicitly mention breaking status. Include a `## Breaking changes` section, or state `No breaking changes`; AutoMerge requires the words `breaking` or `changelog`. |
142 | | -- For subpackage GitHub releases, create annotated tags at current `origin/master`, not the feature branch. Fetch first, verify the tag does not already exist, then tag and publish sequentially. |
143 | | -- Use the exact tag as the GitHub release title, e.g. `KomaMRIBase-v0.11.0`. Put only the provided release notes in the release body. |
144 | | -- Useful pattern: |
145 | | -```bash |
146 | | -git fetch origin master --tags |
147 | | -git tag -a KomaMRIBase-v0.11.0 -F notes.md origin/master |
148 | | -git push origin KomaMRIBase-v0.11.0 |
149 | | -gh release create KomaMRIBase-v0.11.0 --title KomaMRIBase-v0.11.0 --notes-file notes.md |
150 | | -``` |
| 57 | +## PRs And Releases |
| 58 | +- PRs target `master`, stay scoped, and include what changed, why, and what was tested. |
| 59 | +- Add trigger labels at PR creation when the first CI run matters: `documentation`, `run-gpu-ci`, or `pre-release`. Adding them after PR creation is too late for the first run. |
| 60 | +- Release tags are annotated tags on current `origin/master`, not feature branches. |
| 61 | +- Registrator notes must mention breaking status: include `## Breaking changes` or state `No breaking changes`. |
151 | 62 |
|
152 | | -## Canonical References |
| 63 | +## References |
153 | 64 | - Contributor workflow: `docs/src/how-to/5-contribute-to-koma.md` |
154 | 65 | - CI truth: `.github/workflows/CI.yml` and `.github/workflows/CIPreRelease.yml` |
0 commit comments