Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .claude/agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ Run sequentially, reading each agent's findings before launching the next:
3. **`julia-performance-optimizer`** and/or **`fast-interpolations-optimizer`** — only if the change is performance-relevant.
4. **`regression-guardian`** — always, last, before merge. Confirms the numbers didn't silently move.

**These agents are diff-scoped, and that leaves one thing uncovered.** Each reviews what changed, so a
hot path nobody is editing is invisible to all of them — permanently, no matter how expensive it
becomes. `julia-performance-optimizer` in particular is handed a named function and told not to
profile the suite, so it cannot find a hotspot outside the diff and should not be described as though
it had. Whole-program cost is answered only by profiling a full run, which is a developer-initiated
check rather than anything the pipeline does on its own. Two moments are worth spending it on: when a
module first lands in a hot path, and when someone's sense is that runtime has changed a lot. When
asked to do performance work, do not assume the diff is the scope — say what the whole-run cost
picture is, or say that it is unmeasured.

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.

## Budget
Expand Down
20 changes: 20 additions & 0 deletions .claude/agents/julia-performance-optimizer.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,26 @@ You operate under a hard budget to protect the user's token quota:
- For major optimizations, recommend adding benchmark scripts to test/ directory
- Compare performance metrics (time, allocations, memory) between original and optimized versions

## Before optimizing: cost the work, don't just locate it

A profiler says where time goes. It never says what the work *should* cost, and optimizing inside its
framing yields a faster version of an operation that should not exist. Answer both before proposing
any micro-optimization:

1. **What is the mathematical object?** Name the operation and what its data structure already
determines. A level set of a piecewise cubic is a root *formula*, not a search; an integral of a
spline is a closed form. If a general-purpose solver is being called on a structure with an exact
solution, replacing the solver *is* the optimization and everything else is polishing.
2. **What is the cost per work item?** Divide the profile's share by the number of items (calls ×
roots × evaluations) and compare against a first-principles estimate. A ratio of 10× or more means
the algorithm is wrong, not the constants — report that and stop, rather than shaving constants.

Read the **enclosing loop for invariants a profile cannot show**. If an outer loop advances
monotonically, each iteration's answer is a hint for the next and a blind search is waste — the
codebase already uses this idiom through FastInterpolations' `hint=` arguments. Report allocations per
call for any loop running more than ~10³ times, and say plainly when an optimization buys exactness
rather than speed.

## Workflow

When presented with code to optimize, follow this structured approach:
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Roster, the recommended review pipeline (physics fidelity → readability → pe
### Minimal-change discipline
- **Reuse native ops and existing utilities before writing new ones.** FastInterpolations splines integrate and differentiate natively (`integrate`, `cumulative_integrate`, `deriv1`); the Equilibrium module already has flux-surface integration/average patterns. Do not reimplement spline integration, quadrature, or differentiation — grep for the existing idiom first.
- **Size the change to the problem.** A small numerical correction (e.g. a ~1% fix) should be a handful of lines, not new general-purpose machinery. Resist faithfully porting Fortran scaffolding (custom integrators, power-law spline bases) when a native call plus a one-line correction gives the same numbers — verify equivalence instead of assuming the elaborate version is needed.
- **Replacing a solver with its closed form is a reduction, not new machinery.** The rule above targets ported scaffolding, not exact methods. Where the data structure already determines the answer — a spline cell is a cubic, so a level set of it is a root formula and the stationary points are roots of a quadratic — writing that solution and deleting the iterative solver removes machinery even when the line count rises. Justify it with the residual, not the line count.
- **Don't commit throwaway artifacts for minor fixes.** No in-repo benchmark scripts/outputs or agent-memory churn for a small change — these accumulate and outsize `src`. Verify with a scratch script (e.g. under `/tmp`) and the regression harness; the regression harness is the durable record of numerical behavior.

### Output Files
Expand Down
Loading