@@ -12,9 +12,9 @@ The full **fetch → process → service → GUI** path runs end-to-end for **bo
1212 ` data/datafile/ ` (gitignored); read back via ` magnetics.data.h5source ` . The GUI can trigger a
1313 pull from the left rail (` PullControl ` → ` POST /api/fetch ` ).
1414- ** Process:** ` core/spectral.py ` (MODESPEC) is real and pure. The SLCONTOUR quasi-stationary fit
15- runs end-to-end via the reference pipeline in ` magnetics._slcontour/ ` (xarray, self-contained
16- OMFIT shim) adapted by ` core/ qs_bridge` — real K / χ² / modes for shots pulled with the Bp LFS
17- midplane array. A pure ` core/quasistationary ` port exists but is not yet wired in production ( # 40 ) .
15+ runs end-to-end via the shim-free ` core/qs_* ` modules ( ` qs_io_data ` → ` qs_prep ` → ` qs_fit ` ,
16+ adapted to nodes by ` qs_bridge ` ; the former ` _slcontour ` translation, promoted into core) — real
17+ K / χ² / modes for shots pulled with the Bp LFS midplane array .
1818- ** Service:** ` service/app.py ` — ` GET /api/node/{shot}/{node_id} ` serves ` kind ` -nodes from
1919 ` service/nodes.py ` ; ` /api/machines ` lists fetched shots (mock fallback when none).
2020- ** Nodes / seam:** ` nodes.py ` forwards GUI query params and serves the core's real ` mode_number ` /
@@ -31,9 +31,10 @@ The full **fetch → process → service → GUI** path runs end-to-end for **bo
3131 the rotating/MODESPEC nodes and the Sensors view render those shots too.
3232
3333Known gaps / open work: per-sensor σ from the data layer (the QS fit currently uses a constant σ;
34- helicity is computed from Ip·Bt); finishing the pure ` core/quasistationary ` port and wiring it in
35- place of the ` _slcontour ` reference pipeline (#40 ); real equilibrium plotting in the Sensors tab
36- (#43 ); Br saddle-loop geometry corrections (#44 ).
34+ helicity is computed from Ip·Bt); real equilibrium plotting in the Sensors tab (#43 ); the
35+ xarray-heavy ` qs_* ` modules are excluded from the ` ty ` typecheck (see ` [tool.ty.src] ` in
36+ pyproject.toml); the cursor analyses (` phase_fit ` / mode shape) read from a 1–25 kHz cached
37+ array spectrum, so modes above 25 kHz aren't phase-fittable at the cursor.
3738
3839## The API contract is FLEXIBLE — change it, don't fake around it
3940The ` kind ` -node contract (` core/contracts.py ` ⇄ ` gui/web/src/lib/contract.ts ` , plus the
@@ -59,16 +60,27 @@ rather than fabricating data in the GUI. Keep `contracts.py` and `contract.ts` i
5960
6061## Layout
6162The Python project ** is the repo root** (a uv project, served as a webapp). ` src/magnetics/ ` :
62- - ` core/ ` — device-agnostic math (geometry, basis, design metrics, ` quasistationary ` , ` spectral ` ).
63+ - ` core/ ` — device-agnostic math: ` spectral ` (MODESPEC), ` mode_shape ` , ` geometry ` , the
64+ quasi-stationary fit (` qs_io_data ` /` qs_prep ` /` qs_fit ` /` qs_bridge ` /` qs_device ` /` qs_run ` /
65+ ` qs_plots ` ), and the ` contracts ` node shapes.
6366- ` data/ ` — sources + ` fetch/ ` (toksearch/mdsthin pulls, cluster orchestration); device configs
6467 in ` data/device/*.json ` .
6568- ` service/ ` — FastAPI; the built GUI is bundled at ` service/webapp/ ` and served here.
66- - ` _slcontour/ ` — the reference SLCONTOUR translation (self-contained OMFIT shim), pending port
67- into ` core/quasistationary ` (issue #40 ); ** excluded from lint/typecheck** until then.
6869
6970Tests in ` tests/ ` , maintainer scripts in ` scripts/ ` . ` gui/web/ ` — React + Vite + TypeScript
7071frontend (its ` dist/ ` is staged into ` service/webapp/ ` for the wheel).
7172
73+ ## Running the tests
74+ - ** Python:** ` uv run pytest ` from the repo root — the whole suite is offline and deterministic
75+ (~ 5 s; synthetic fixtures are generated at collection time, no real data needed). Live-network
76+ tests (GA gateway / PPPL flux) are env-gated and skip unless ` MAGNETICS_GA_USER ` /
77+ ` MAGNETICS_FLUX_USER ` is set; they are manual-only, never wired into CI.
78+ - ** Frontend:** ` cd gui/web && npm run test ` (vitest, one-shot; ` npm run test:watch ` to iterate).
79+ - ** Everything CI runs:** ` uv run ruff format --check . ` + ` uvx ruff check . ` + ` uv run pytest `
80+ + ` uv run ty check src/magnetics ` (Python), and ` npm run lint ` + ` npm run typecheck ` +
81+ ` npm run test ` + ` npm run build ` (in ` gui/web/ ` ). Run these locally before committing —
82+ a plain ` pytest ` + ` tsc ` pass does NOT cover everything CI checks.
83+
7284## Conventions
7385- Physics lives in ` src/magnetics/core ` (pure, device-agnostic, testable); ** no physics in the
7486 service routes** .
0 commit comments