Skip to content

Commit 5717764

Browse files
authored
Merge branch 'develop' into feature/tearing-growthrates
2 parents 5b45e20 + 167ada7 commit 5717764

63 files changed

Lines changed: 1938 additions & 2628 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/agents/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Agent Team
2+
3+
This repo ships a small team of specialized Claude Code subagents in `.claude/agents/`. They are **stateless reviewers**: each runs in its own context, is handed a specific deliverable, and returns its findings to the main session — they do not talk to each other. **The main session is the integrator.** You drive them; you do not delegate the whole task and walk away.
4+
5+
**Invoke an agent by name** for the matching job — e.g. *"review this with the fortran-physics-reviewer"* or *"run the regression-guardian against develop"*. Do **not** "consult all the agents" reflexively: that burns the token budget and produces noise. Pick the agent whose job matches the change.
6+
7+
## Roster
8+
9+
| Agent | Model | Role — invoke when… |
10+
|---|---|---|
11+
| `fortran-physics-reviewer` | opus | A physics kernel, numerical method, derivative, integral, or quadrature was written/changed. Audits fidelity to the reference papers and the Fortran GPEC source. Carries project memory (correspondence map + per-domain audit checklists for KineticForces and InnerLayer), so its reviews compound — let it record findings. |
12+
| `clean-code-reviewer` | opus | A logical chunk of code is ready and you want readability/maintainability review for a fusion physicist audience (naming, magic numbers, docstrings, structure). |
13+
| `julia-performance-optimizer` | opus | A specific function/hotspot is slow or perf-sensitive (type stability, allocations, hot-loop work in ODE/kinetic/resistive-layer paths). |
14+
| `fast-interpolations-optimizer` | opus | Code uses FastInterpolations.jl and you want allocation-free / optimal-search-type review. |
15+
| `regression-guardian` | sonnet | **Before merging any substantive change** (mandatory per the Regression Harness policy — see `docs/development/regression-harness.md`), or when you need to know whether a tracked numerical quantity moved. Runs the harness, reports the table, flags non-OK rows, proposes new cases. |
16+
17+
## Recommended review pipeline for a substantive change
18+
19+
Run sequentially, reading each agent's findings before launching the next:
20+
21+
1. **`fortran-physics-reviewer`** — physics fidelity first; a fast-but-wrong result is worthless.
22+
2. **`clean-code-reviewer`** — readability and maintainability.
23+
3. **`julia-performance-optimizer`** and/or **`fast-interpolations-optimizer`** — only if the change is performance-relevant.
24+
4. **`regression-guardian`** — always, last, before merge. Confirms the numbers didn't silently move.
25+
26+
Not every change needs all four. A docs-only change needs none; a pure perf refactor still needs the physics reviewer (to confirm no numerical change) and the regression-guardian.
27+
28+
## Budget
29+
30+
Every consultation is bounded — see **Subagent Consultations** in `/CLAUDE.md` (≤30 tool uses, ≤10 min, one concrete deliverable, never re-launch a runaway). The agent bodies now self-enforce this, but state the budget in your prompt anyway and always hand the agent the specific file paths to act on.

.github/workflows/claude-code-review.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
contains(github.event.comment.body, '@claude review')
1414
1515
runs-on: ubuntu-latest
16+
timeout-minutes: 60
1617
permissions:
1718
contents: read
1819
pull-requests: read
@@ -21,7 +22,7 @@ jobs:
2122

2223
steps:
2324
- name: Checkout repository
24-
uses: actions/checkout@v4
25+
uses: actions/checkout@v6
2526
with:
2627
fetch-depth: 1
2728

.github/workflows/claude.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ jobs:
1818
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && !contains(github.event.review.body, '@claude review')) ||
1919
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
2020
runs-on: ubuntu-latest
21+
timeout-minutes: 60
2122
permissions:
2223
contents: read
2324
pull-requests: read
@@ -26,7 +27,7 @@ jobs:
2627
actions: read # Required for Claude to read CI results on PRs
2728
steps:
2829
- name: Checkout repository
29-
uses: actions/checkout@v4
30+
uses: actions/checkout@v6
3031
with:
3132
fetch-depth: 1
3233

.github/workflows/copilot-setup-steps.yaml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,37 @@ on:
66
workflow_dispatch:
77
push:
88
paths:
9-
- .github/workflows/copilot-setup-steps.yml
9+
- .github/workflows/copilot-setup-steps.yaml
1010
pull_request:
1111
paths:
12-
- . github/workflows/copilot-setup-steps.yml
12+
- .github/workflows/copilot-setup-steps.yaml
1313

1414
jobs:
1515
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot
1616
copilot-setup-steps:
1717
runs-on: ubuntu-latest
18+
timeout-minutes: 30
1819

1920
# Set the permissions to the lowest permissions possible needed for your steps
2021
permissions:
2122
contents: read
2223

2324
steps:
2425
- name: Checkout code
25-
uses: actions/checkout@v4
26+
uses: actions/checkout@v6
2627

2728
- name: Set up Julia
2829
uses: julia-actions/setup-julia@v2
2930
with:
30-
version: '1.11'
31+
version: '1.11'
3132

3233
- name: Cache Julia packages
33-
uses: julia-actions/cache@v2
34+
uses: julia-actions/cache@v3
3435
with:
3536
cache-name: julia-cache
3637
cache-packages: true
3738
cache-artifacts: true
3839
cache-registries: true
3940

40-
- name: Instantiate Julia environment
41+
- name: Instantiate Julia environment
4142
run: julia --project="." -e "using Pkg; Pkg.instantiate()"

.github/workflows/format.yaml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Format and Hygiene
2+
3+
# Runs the repository's pre-commit suite (JuliaFormatter + file hygiene) so that
4+
# contributors who have not run `pre-commit install` locally are still caught.
5+
#
6+
# DISABLED as a pull request gate for now: the repository has pre-existing
7+
# formatting drift that has to be cleaned up first. Until then, run this
8+
# manually from the Actions tab ("Run workflow") to see the current damage.
9+
#
10+
# To enable it as a gate, uncomment the `pull_request` trigger below. If the
11+
# test suite's `Tests` job is a required status check, add `pre-commit` too.
12+
on:
13+
workflow_dispatch:
14+
# pull_request:
15+
# branches:
16+
# - main
17+
# - develop
18+
19+
permissions:
20+
contents: read
21+
22+
concurrency:
23+
group: ${{ github.workflow }}-${{ github.ref }}
24+
cancel-in-progress: true
25+
26+
jobs:
27+
pre-commit:
28+
name: pre-commit
29+
runs-on: ubuntu-latest
30+
timeout-minutes: 20
31+
steps:
32+
- name: Checkout repository
33+
uses: actions/checkout@v6
34+
35+
- name: Set up Python
36+
uses: actions/setup-python@v5
37+
with:
38+
# Matches default_language_version in .pre-commit-config.yaml
39+
python-version: '3.10'
40+
41+
- name: Set up Julia
42+
uses: julia-actions/setup-julia@v2
43+
with:
44+
version: '1.11'
45+
46+
# The julia-formatter hook is `language: system`: it shells out to
47+
# `julia -e 'import JuliaFormatter: format; format(ARGS)'` and therefore
48+
# uses whatever JuliaFormatter lives in the default depot environment.
49+
# Pin it to the same version .pre-commit-config.yaml pins the hook repo
50+
# to, otherwise CI and local pre-commit runs disagree on formatting.
51+
- name: Install JuliaFormatter
52+
run: julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter", version="1.0.62"))'
53+
54+
- name: Cache pre-commit environments
55+
uses: actions/cache@v4
56+
with:
57+
path: ~/.cache/pre-commit
58+
key: pre-commit-${{ runner.os }}-py3.10-${{ hashFiles('.pre-commit-config.yaml') }}
59+
restore-keys: |
60+
pre-commit-${{ runner.os }}-py3.10-
61+
62+
- name: Run pre-commit
63+
run: |
64+
python -m pip install --upgrade pre-commit
65+
pre-commit run --all-files --show-diff-on-failure --color=always

.github/workflows/make_docs.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
docs:
2020
name: Documentation
2121
runs-on: ubuntu-latest
22+
timeout-minutes: 60
2223
permissions:
2324
actions: write
2425
contents: write

.github/workflows/test.yaml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,83 @@ permissions:
1515
actions: write
1616
contents: read
1717

18+
concurrency:
19+
# One in-flight run per branch/PR. Superseded pull request runs are cancelled;
20+
# runs on main/develop are allowed to finish so every merged commit is verified.
21+
group: ${{ github.workflow }}-${{ github.ref }}
22+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
23+
1824
jobs:
25+
changes:
26+
name: Detect Julia changes
27+
runs-on: ubuntu-latest
28+
timeout-minutes: 5
29+
permissions:
30+
contents: read
31+
pull-requests: read
32+
outputs:
33+
julia: ${{ steps.filter.outputs.julia }}
34+
steps:
35+
- name: Check whether the pull request touches Julia code
36+
id: filter
37+
env:
38+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39+
REPO: ${{ github.repository }}
40+
PR_NUMBER: ${{ github.event.pull_request.number }}
41+
run: |
42+
set -euo pipefail
43+
44+
# Report the decision to the job log as well as the run summary, so
45+
# `why did/didn't this run?` is answerable from either one.
46+
say() { echo "$1"; echo "$1" >> "$GITHUB_STEP_SUMMARY"; }
47+
48+
# Pushes to main/develop always run: every merged commit gets verified.
49+
if [ "${{ github.event_name }}" != "pull_request" ]; then
50+
echo "julia=true" >> "$GITHUB_OUTPUT"
51+
say "Not a pull request — running the full test suite."
52+
exit 0
53+
fi
54+
55+
files=$(gh api --paginate "repos/${REPO}/pulls/${PR_NUMBER}/files" --jq '.[].filename')
56+
57+
# Allowlist of what test/runtests.jl actually exercises: the package
58+
# itself, the tests and their fixtures, the example decks the tests run
59+
# end-to-end, the dependency set, and this workflow. Anything not listed
60+
# here does not trigger a run, so new untested Julia (benchmarks, docs
61+
# scripts, a future tools/ directory) is excluded by default rather than
62+
# by remembering to exclude it.
63+
tested='(^src/|^test/|^examples/|^Project\.toml$|^\.github/workflows/test\.yaml$)'
64+
65+
relevant=$(printf '%s\n' "$files" | grep -E "$tested" || true)
66+
67+
say "### Julia change detection"
68+
say ""
69+
if [ -n "$relevant" ]; then
70+
say "Running the test suite. Matched files:"
71+
say '```'
72+
say "$relevant"
73+
say '```'
74+
else
75+
say "No Julia code, test data or example decks changed — skipping the test suite."
76+
say ""
77+
say "Files considered:"
78+
say '```'
79+
say "$files"
80+
say '```'
81+
fi
82+
83+
if [ -n "$relevant" ]; then
84+
echo "julia=true" >> "$GITHUB_OUTPUT"
85+
else
86+
echo "julia=false" >> "$GITHUB_OUTPUT"
87+
fi
88+
1989
test:
2090
name: runtests ${{ matrix.version }} - ${{ matrix.os }}
91+
needs: changes
92+
if: needs.changes.outputs.julia == 'true'
2193
runs-on: ${{ matrix.os }}
94+
timeout-minutes: 90
2295
strategy:
2396
fail-fast: false
2497
matrix:
@@ -43,5 +116,33 @@ jobs:
43116
- name: Build Julia packages
44117
uses: julia-actions/julia-buildpkg@v1
45118

119+
# Coverage instrumentation is off: nothing consumes the .cov files (they are
120+
# gitignored and never uploaded), and instrumenting slows compute-heavy
121+
# numerical code noticeably. Set coverage: true and add a Codecov upload
122+
# step together if coverage reporting is ever wanted.
46123
- name: Run tests
47124
uses: julia-actions/julia-runtest@v1
125+
with:
126+
coverage: false
127+
128+
# Stable check that is present on every pull request, whether or not the suite
129+
# ran. Point branch protection at this job so skipped runs do not block merges.
130+
test-status:
131+
name: Tests
132+
needs: [changes, test]
133+
if: always()
134+
runs-on: ubuntu-latest
135+
timeout-minutes: 5
136+
steps:
137+
- name: Report suite result
138+
run: |
139+
set -euo pipefail
140+
if [ "${{ needs.changes.result }}" != "success" ]; then
141+
echo "Change detection failed; cannot tell whether tests were needed."
142+
exit 1
143+
fi
144+
case "${{ needs.test.result }}" in
145+
success) echo "Test suite passed." ;;
146+
skipped) echo "No Julia code changed; test suite intentionally skipped." ;;
147+
*) echo "Test suite result: ${{ needs.test.result }}"; exit 1 ;;
148+
esac

0 commit comments

Comments
 (0)