Kronos Fusion Energy commited on
Commit
2573a5a
·
1 Parent(s): 102af5d

Refresh to v0.3.0 (39 codes); clean package + docs (drop stale cache dump and deposit tooling)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +0 -35
  2. .pytest_cache/.gitignore +0 -2
  3. .pytest_cache/CACHEDIR.TAG +0 -4
  4. .pytest_cache/README.md +0 -8
  5. .pytest_cache/v/cache/lastfailed +0 -3
  6. .pytest_cache/v/cache/nodeids +0 -12
  7. .zenodo.json +4 -4
  8. BENCHMARKS.md +25 -21
  9. CITATION.cff +2 -2
  10. CODES.md +16 -0
  11. benchmarks/benchmarks.json +427 -16
  12. benchmarks/run_all.py +25 -0
  13. codemeta.json +2 -2
  14. kronos_ml/members/__init__.py +2 -0
  15. kronos_ml/members/advanced.py +133 -0
  16. kronos_ml/members/foundation.py +333 -0
  17. kronos_ml/members/quantum.py +8 -7
  18. kronos_ml/members/quantum_v3.py +286 -0
  19. kronos_ml/quantum_backend.py +3 -2
  20. publish/LIVE_RECORDS.md +0 -36
  21. publish/MANIFEST.sha256 +0 -41
  22. publish/PROVENANCE.md +0 -42
  23. publish/PUBLISH_RUNBOOK.md +0 -158
  24. publish/_deposit_common.py +0 -68
  25. publish/_percode.py +0 -256
  26. publish/_percode_summary.json +0 -42
  27. publish/_scaffolding_summary.json +0 -40
  28. publish/dataverse_draft.py +0 -105
  29. publish/dataverse_publish_all.py +0 -59
  30. publish/figshare_draft.py +0 -119
  31. publish/figshare_publish_all.py +0 -47
  32. publish/ia_upload_all.py +0 -47
  33. publish/kronos-ml-v0.1.0-source.zip +0 -3
  34. publish/osf_draft.py +0 -71
  35. publish/osf_publish_all.py +0 -47
  36. publish/records/kairos/CITATION.cff +0 -13
  37. publish/records/kairos/LICENSE +0 -189
  38. publish/records/kairos/MANIFEST.sha256 +0 -7
  39. publish/records/kairos/benchmark.json +0 -19
  40. publish/records/kairos/card.md +0 -13
  41. publish/records/kairos/kairos.py +0 -57
  42. publish/records/kairos/metadata.json +0 -65
  43. publish/records/kbench/CITATION.cff +0 -13
  44. publish/records/kbench/LICENSE +0 -189
  45. publish/records/kbench/MANIFEST.sha256 +0 -7
  46. publish/records/kbench/benchmark.json +0 -44
  47. publish/records/kbench/card.md +0 -13
  48. publish/records/kbench/kbench.py +0 -54
  49. publish/records/kbench/metadata.json +0 -65
  50. publish/records/kbreed/CITATION.cff +0 -13
.gitattributes DELETED
@@ -1,35 +0,0 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.pytest_cache/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- # Created by pytest automatically.
2
- *
 
 
 
.pytest_cache/CACHEDIR.TAG DELETED
@@ -1,4 +0,0 @@
1
- Signature: 8a477f597d28d172789f06886806bc55
2
- # This file is a cache directory tag created by pytest.
3
- # For information about cache directory tags, see:
4
- # https://bford.info/cachedir/spec.html
 
 
 
 
 
.pytest_cache/README.md DELETED
@@ -1,8 +0,0 @@
1
- # pytest cache directory #
2
-
3
- This directory contains data from the pytest's cache plugin,
4
- which provides the `--lf` and `--ff` options, as well as the `cache` fixture.
5
-
6
- **Do not** commit this to version control.
7
-
8
- See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information.
 
 
 
 
 
 
 
 
 
.pytest_cache/v/cache/lastfailed DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "tests/test_contract.py::test_registry_has_thirty": true
3
- }
 
 
 
 
.pytest_cache/v/cache/nodeids DELETED
@@ -1,12 +0,0 @@
1
- [
2
- "tests/test_contract.py::test_contract_returns_prediction",
3
- "tests/test_contract.py::test_every_code_has_provenance_and_status",
4
- "tests/test_contract.py::test_kecon_financial_firewall",
5
- "tests/test_contract.py::test_kgate_clamps_and_fails_closed",
6
- "tests/test_contract.py::test_kyro_reproduces_training_point",
7
- "tests/test_contract.py::test_metrics_calibration",
8
- "tests/test_contract.py::test_registry",
9
- "tests/test_contract.py::test_registry_has_thirty",
10
- "tests/test_contract.py::test_roadmap_codes_raise",
11
- "tests/test_contract.py::test_tagged_provenance_requires_retired_by"
12
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
.zenodo.json CHANGED
@@ -1,9 +1,9 @@
1
  {
2
- "title": "KODEX: the Kronos Family of Codes (AI/ML fusion surrogate suite) v0.1.0",
3
  "upload_type": "software",
4
  "language": "eng",
5
- "version": "0.1.0",
6
- "publication_date": "2026-09-10",
7
  "creators": [
8
  {
9
  "name": "Ford, P. I.",
@@ -193,5 +193,5 @@
193
  }
194
  ],
195
  "notes": "Draft-first deposit. Provenance chain: code -> benchmark -> on-disk data -> CGYRO/register/AI+Quantum DOI. See PROVENANCE.md and MANIFEST.sha256.",
196
- "description": "<p><strong>KODEX &mdash; the Kronos Family of Codes.</strong> A benchmarked suite of AI/ML surrogate models that stand in for expensive fusion physics (CGYRO-class gyrokinetics, neutronics, equilibrium, control) with calibrated uncertainty and an abstention gate. One contract across the fleet: <code>predict(x) &rarr; (y, uncertainty, in_domain)</code>. Built on and tracing to the Kronos research corpus.</p><p>This release publishes the <strong>26 BUILT</strong> codes (package + real benchmark + docs). 4 further codes ship as honest ROADMAP: KEDGE, KHEAT, KRAD, KTENSOR.</p><p>Honest cards are kept intact: CGYRO-anchored surrogates use the mu=400 representative-mass turbulence map; the quantum members (KQUBIT/KQROSS/KSENSE) report validated null/negative results (no quantum advantage claimed); KWARD's disruption labels are heuristic (Ip current-quench, not physicist-verified) and its headline independent-precursor AUC (0.975) uses only n=1 Mirnov + P_rad; KECON is a generic-LCOE financial firewall carrying no Kronos economic numbers.</p><p>Documentation: <a href=\"https://kronosfusionenergy.com/kodex\">https://kronosfusionenergy.com/kodex</a> &middot; source: <a href=\"https://github.com/KronosFE/kronos-ml\">https://github.com/KronosFE/kronos-ml</a>.</p>"
197
  }
 
1
  {
2
+ "title": "KODEX: the Kronos Family of Codes (AI/ML fusion surrogate suite) v0.3.0",
3
  "upload_type": "software",
4
  "language": "eng",
5
+ "version": "0.3.0",
6
+ "publication_date": "2026-09-29",
7
  "creators": [
8
  {
9
  "name": "Ford, P. I.",
 
193
  }
194
  ],
195
  "notes": "Draft-first deposit. Provenance chain: code -> benchmark -> on-disk data -> CGYRO/register/AI+Quantum DOI. See PROVENANCE.md and MANIFEST.sha256.",
196
+ "description": "<p><strong>KODEX &mdash; the Kronos Family of Codes.</strong> A benchmarked suite of AI/ML surrogate models that stand in for expensive fusion physics (CGYRO-class gyrokinetics, neutronics, equilibrium, control) with calibrated uncertainty and an abstention gate. One contract across the fleet: <code>predict(x) &rarr; (y, uncertainty, in_domain)</code>. Built on and tracing to the Kronos research corpus.</p><p>This release publishes the full <strong>39 BUILT</strong> codes (package + real benchmark + docs), including the v0.3.0 additions KMIND (whole-device foundation surrogate), KSCOUT (multi-fidelity campaign manager), and the quantum members KMIT (error mitigation) and KLINQ (linear solver).</p><p>Honest cards are kept intact: CGYRO-anchored surrogates use the mu=400 representative-mass turbulence map; the quantum members (KQUBIT/KQROSS/KSENSE) report validated null/negative results (no quantum advantage claimed); KWARD's disruption labels are heuristic (Ip current-quench, not physicist-verified) and its headline independent-precursor AUC (0.975) uses only n=1 Mirnov + P_rad; KECON is a generic-LCOE financial firewall carrying no Kronos economic numbers; the newer quantum members (KMIT, KLINQ) are real NISQ-era tools with no claimed advantage &mdash; quantum's meaningful role in fusion is post-~2036.</p><p>Documentation: <a href=\"https://kronosfusionenergy.com/kodex\">https://kronosfusionenergy.com/kodex</a> &middot; source: <a href=\"https://github.com/KronosFE/kronos-ml\">https://github.com/KronosFE/kronos-ml</a>.</p>"
197
  }
BENCHMARKS.md CHANGED
@@ -6,16 +6,16 @@ are kept, not hidden. Nothing here is published until go-live.
6
 
7
  | # | Code | Status | Headline benchmark |
8
  |--|--|--|--|
9
- | 01 | **KAIROS** | BUILT | MPC tracking 0.0461 (<5%); Exp-B **0 escapes / 150,000**; 155.4 µs/step |
10
  | 02 | **KFLOW** | BUILT | GNN RMSE@k8 0.0844 vs naive 0.1721 (beats naive; AC-18 0.05 bar **MISSED**, kept) |
11
  | 03 | **KGATE** | BUILT | model-free clamp: **0 escapes / 150,000 steps** |
12
  | 04 | **KHALO** | BUILT | sourced ECE 0.0327 +/- 0.0136 / cov90 0.888 +/- 0.034; live GP ECE 0.0771 |
13
  | 05 | **KMAT** | BUILT | DFT-validated CHGNet screen, 8 candidates |
14
  | 06 | **KOIL** | BUILT | live strain surrogate rel-L2 0.0038; sourced 0.24% @0.15 ms, quench AUC 0.9998 |
15
- | 07 | **KORE** | BUILT | learned NN equilibrium: rel-L2 0.0035 vs analytic, 2.337 ms/field; sourced FNO 2.5% vs 1% bar |
16
  | 08 | **KQUBIT** | BUILT | **REAL VQE** (PennyLane): recovers H2 ground state to 0.0002 mHa on default; runs on real QC hardware — no advantage yet |
17
  | 09 | **KWARD** | BUILT | real-device AUC 0.98 (591 MAST shots), ECE 0.0349; **independent-precursor AUC 0.975** (n=1 Mirnov + P_rad ONLY, label-independent); labels heuristic (Ip-quench) |
18
- | 10 | **KYRO** | BUILT | complete 16/16 map (12 turbulent / 4 quiet (16/16 complete)); turbulent/quiet **16/16 correct**, R²=0.858 / cov90=0.875; **0.329 ms vs 2.89 GPU-h/pt** (μ=400) |
19
  | 11 | **KBREED** | BUILT | TBR surrogate R²=1.0 vs neutronics engine; nominal net TBR 0.742; OpenMC = auto fidelity upgrade |
20
  | 12 | **KBURN** | BUILT | dispatch surrogate R²=1.0 (fuel mix → captured power); +22% dynamic |
21
  | 13 | **KEYE** | BUILT | virtual-sensor fault detection 0.767 at FAR 0.0 |
@@ -23,23 +23,27 @@ are kept, not hidden. Nothing here is published until go-live.
23
  | 15 | **KFUSE** | BUILT | multi-fidelity: RMSE 1.481→1.05 (R²=0.787); 3rd fidelity = real-mass gold (deferred) |
24
  | 16 | **KHEAT** | BUILT | heating/current-drive surrogate: driven-current I_cd **R²=0.949** over 3888 configs (reduced CD; RF/NBI ray-tracing = upgrade) |
25
  | 17 | **KISO** | BUILT | servo R²=0.723 + **medical-isotope yield** from real FENDL-3.2 σ(E) (6 isotopes, Mo-99/Tc-99m flagship) |
26
- | 18 | **KPATH** | BUILT | MPC-imitation controller R²=0.879 over 6 axes |
27
- | 19 | **KQERN** | BUILT | **REAL quantum kernel**: MAST-disruption AUC 0.919 vs classical 0.929 (ties — honest null); runnable on real QC hardware |
28
- | 20 | **KQROSS** | BUILT | **REAL FT resource estimator**: classical↔quantum crossover ~N=50 needs ~6e+04 physical qubits, roadmap ~2032 — no FT advantage this decade |
29
- | 21 | **KSENSE** | BUILT | **REAL quantum metrology** (GHZ, PennyLane): ideal Heisenberg 4.0× vs dephased 2.05× ≈ SQL 2.01× — dephasing erases the advantage (honest null) |
30
- | 22 | **KTENSOR** | BUILT | SVD/MPS ROM of the real CGYRO flux DB: **effective rank ~2.93 of 4 — modestly compressible, NOT strongly low-rank** (honest characterization; classical, no quantum advantage) |
31
- | 23 | **KBENCH** | BUILT | open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselines |
32
- | 24 | **KDRIVE** | BUILT | RL policy (cross-entropy): tracking **0.0551** vs naive 0.1225, twin-in-the-loop |
33
- | 25 | **KDYN** | BUILT | **REAL Trotter quantum dynamics**: 1st-order error 1.34637→0.03381 over steps (~1/n); runs on real QC hardware — honest cost curve, no advantage yet |
34
- | 26 | **KECON** | BUILT | generic LCOE calculator + breakdown — **FINANCIAL FIREWALL (no Kronos numbers)** |
35
- | 27 | **KEDGE** | BUILT | divertor edge surrogate: heat-flux→target-temp **R²=1.0**, CuCrZr limit q~13.5 MW/m² (reduced 0-D; SOLPS/EIRENE = upgrade) |
36
- | 28 | **KFORGE** | BUILT | inverse-design chained KYRO+KORE → **found a quiet operating point** (a/L_T=2.228, shear=1.511, Q_tot≈0.0) |
37
- | 29 | **KFUEL** | BUILT | fuel-cycle balance: self-sufficient=True, doubling 5.17 yr (illustrative TBR) |
38
- | 30 | **KGEN** | BUILT | generative (PCA latent, dim 8); samples plausible equilibrium fields (diffusion = roadmap) |
39
- | 31 | **KLAW** | BUILT | equation discovery: 7 terms, R²=0.903 — **rediscovered the critical-gradient onset** from the CGYRO map |
40
- | 32 | **KPILOT** | BUILT | fleet router: plain-language query → the right code (LLM agent = roadmap upgrade) |
41
- | 33 | **KQOPT** | BUILT | **REAL QAOA optimizer**: 1.0 of optimum on a design QUBO (6 qubits); plug in your QUBO, run on real QC hardware — no speedup yet |
42
- | 34 | **KRAD** | BUILT | impurity-seeding radiation evaluator: 3 impurities (Ar, N, Ne); least core dilution = Ar |
43
- | 35 | **KSEEK** | BUILT | active-learning: proposes next CGYRO run (a/L_T=2.225, shear=0.58); LOO std-vs-error corr -0.283 (honest: weak on 16 pts) |
 
 
 
 
44
 
45
  _Regenerate: `PYTHONPATH=<kronos-ml>:<kronos-toolkit> python benchmarks/run_all.py`._
 
6
 
7
  | # | Code | Status | Headline benchmark |
8
  |--|--|--|--|
9
+ | 01 | **KAIROS** | BUILT | MPC tracking 0.0461 (<5%); Exp-B **0 escapes / 150,000**; 77.8 µs/step |
10
  | 02 | **KFLOW** | BUILT | GNN RMSE@k8 0.0844 vs naive 0.1721 (beats naive; AC-18 0.05 bar **MISSED**, kept) |
11
  | 03 | **KGATE** | BUILT | model-free clamp: **0 escapes / 150,000 steps** |
12
  | 04 | **KHALO** | BUILT | sourced ECE 0.0327 +/- 0.0136 / cov90 0.888 +/- 0.034; live GP ECE 0.0771 |
13
  | 05 | **KMAT** | BUILT | DFT-validated CHGNet screen, 8 candidates |
14
  | 06 | **KOIL** | BUILT | live strain surrogate rel-L2 0.0038; sourced 0.24% @0.15 ms, quench AUC 0.9998 |
15
+ | 07 | **KORE** | BUILT | learned NN equilibrium: rel-L2 0.0035 vs analytic, 0.318 ms/field; sourced FNO 2.5% vs 1% bar |
16
  | 08 | **KQUBIT** | BUILT | **REAL VQE** (PennyLane): recovers H2 ground state to 0.0002 mHa on default; runs on real QC hardware — no advantage yet |
17
  | 09 | **KWARD** | BUILT | real-device AUC 0.98 (591 MAST shots), ECE 0.0349; **independent-precursor AUC 0.975** (n=1 Mirnov + P_rad ONLY, label-independent); labels heuristic (Ip-quench) |
18
+ | 10 | **KYRO** | BUILT | complete 16/16 map (12 turbulent / 4 quiet (16/16 complete)); turbulent/quiet **16/16 correct**, R²=0.858 / cov90=0.875; **0.257 ms vs 2.89 GPU-h/pt** (μ=400) |
19
  | 11 | **KBREED** | BUILT | TBR surrogate R²=1.0 vs neutronics engine; nominal net TBR 0.742; OpenMC = auto fidelity upgrade |
20
  | 12 | **KBURN** | BUILT | dispatch surrogate R²=1.0 (fuel mix → captured power); +22% dynamic |
21
  | 13 | **KEYE** | BUILT | virtual-sensor fault detection 0.767 at FAR 0.0 |
 
23
  | 15 | **KFUSE** | BUILT | multi-fidelity: RMSE 1.481→1.05 (R²=0.787); 3rd fidelity = real-mass gold (deferred) |
24
  | 16 | **KHEAT** | BUILT | heating/current-drive surrogate: driven-current I_cd **R²=0.949** over 3888 configs (reduced CD; RF/NBI ray-tracing = upgrade) |
25
  | 17 | **KISO** | BUILT | servo R²=0.723 + **medical-isotope yield** from real FENDL-3.2 σ(E) (6 isotopes, Mo-99/Tc-99m flagship) |
26
+ | 18 | **KMIT** | BUILT | **REAL error mitigation**: ZNE cuts H2 energy error 44.38→5.029 mHa (0.887 removed); readout TV 0.1472→0.0 — real NISQ tool today, role post-~2036 |
27
+ | 19 | **KPATH** | BUILT | MPC-imitation controller R²=0.879 over 6 axes |
28
+ | 20 | **KQERN** | BUILT | **REAL quantum kernel**: MAST-disruption AUC 0.919 vs classical 0.929 (ties — honest null); runnable on real QC hardware |
29
+ | 21 | **KQROSS** | BUILT | **REAL FT resource estimator**: classical↔quantum crossover ~N=50 needs ~6e+04 physical qubits, roadmap ~2032 — no FT advantage this decade |
30
+ | 22 | **KSENSE** | BUILT | **REAL quantum metrology** (GHZ, PennyLane): ideal Heisenberg 4.0× vs dephased 2.05× ≈ SQL 2.01× — dephasing erases the advantage (honest null) |
31
+ | 23 | **KTENSOR** | BUILT | SVD/MPS ROM of the real CGYRO flux DB: **effective rank ~2.93 of 4 — modestly compressible, NOT strongly low-rank** (honest characterization; classical, no quantum advantage) |
32
+ | 24 | **KBENCH** | BUILT | open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselines |
33
+ | 25 | **KDRIVE** | BUILT | RL policy (cross-entropy): tracking **0.0551** vs naive 0.1225, twin-in-the-loop |
34
+ | 26 | **KDYN** | BUILT | **REAL Trotter quantum dynamics**: 1st-order error 1.34637→0.03381 over steps (~1/n); runs on real QC hardware — honest cost curve, no advantage yet |
35
+ | 27 | **KECON** | BUILT | generic LCOE calculator + breakdown — **FINANCIAL FIREWALL (no Kronos numbers)** |
36
+ | 28 | **KEDGE** | BUILT | divertor edge surrogate: heat-flux→target-temp **R²=1.0**, CuCrZr limit q~13.5 MW/m² (reduced 0-D; SOLPS/EIRENE = upgrade) |
37
+ | 29 | **KFORGE** | BUILT | inverse-design chained KYRO+KORE → **found a quiet operating point** (a/L_T=2.228, shear=1.511, Q_tot≈0.0) |
38
+ | 30 | **KFUEL** | BUILT | fuel-cycle balance: self-sufficient=True, doubling 5.17 yr (illustrative TBR) |
39
+ | 31 | **KGEN** | BUILT | generative (PCA latent, dim 8); samples plausible equilibrium fields (diffusion = roadmap) |
40
+ | 32 | **KLAW** | BUILT | equation discovery: 7 terms, R²=0.903 — **rediscovered the critical-gradient onset** from the CGYRO map |
41
+ | 33 | **KLINQ** | BUILT | **REAL quantum linear solver** (VQLS): 4×4 reduced-MHD solve fidelity 1.0 vs classical (rel-resid 0.0); FT-HHL ~4e+04 phys qubits — no advantage, role post-~2036 |
42
+ | 34 | **KMIND** | BUILT | **foundation model**: one shared trunk across 4 domains (66958 params); transfer vs matched single-task — pos ['equil'], neg none, neutral ['state', 'disrupt'] (transport data-starved) — honest multi-task result |
43
+ | 35 | **KPILOT** | BUILT | fleet router: plain-language query → the right code (LLM agent = roadmap upgrade) |
44
+ | 36 | **KQOPT** | BUILT | **REAL QAOA optimizer**: 1.0 of optimum on a design QUBO (6 qubits); plug in your QUBO, run on real QC hardware — no speedup yet |
45
+ | 37 | **KRAD** | BUILT | impurity-seeding radiation evaluator: 3 impurities (Ar, N, Ne); least core dilution = Ar |
46
+ | 38 | **KSCOUT** | BUILT | **multi-fidelity campaign**: tight 15.0 GPU-h over 16 hotspots → mean confidence ρ 0.638 vs 0.281 all-μ=400 (2.27×); triage-then-escalate |
47
+ | 39 | **KSEEK** | BUILT | active-learning: proposes next CGYRO run (a/L_T=2.225, shear=0.58); LOO std-vs-error corr -0.283 (honest: weak on 16 pts) |
48
 
49
  _Regenerate: `PYTHONPATH=<kronos-ml>:<kronos-toolkit> python benchmarks/run_all.py`._
CITATION.cff CHANGED
@@ -1,8 +1,8 @@
1
  cff-version: 1.2.0
2
  message: "If you use KODEX, please cite it as below."
3
  title: "KODEX: the Kronos Family of Codes (AI/ML fusion surrogate suite)"
4
- version: "0.1.0"
5
- date-released: "2026-09-10"
6
  license: Apache-2.0
7
  repository-code: "https://github.com/KronosFE/kronos-ml"
8
  url: "https://kronosfusionenergy.com/kodex"
 
1
  cff-version: 1.2.0
2
  message: "If you use KODEX, please cite it as below."
3
  title: "KODEX: the Kronos Family of Codes (AI/ML fusion surrogate suite)"
4
+ version: "0.3.0"
5
+ date-released: "2026-09-29"
6
  license: Apache-2.0
7
  repository-code: "https://github.com/KronosFE/kronos-ml"
8
  url: "https://kronosfusionenergy.com/kodex"
CODES.md CHANGED
@@ -94,6 +94,10 @@ tensor-network / low-rank (MPS-style SVD) ROM of the real CGYRO A1e flux databas
94
  **REAL quantum kernel** (PennyLane) — embeds real MAST disruption features into a quantum feature map and classifies on the fidelity kernel; runs on a simulator now, real QC hardware pluggable. MAST-disruption AUC **0.919** vs classical RBF 0.929 (ties — a validated null); a real, runnable quantum-ML pipeline on real fusion data.
95
  *provenance SIM · retired_by **fault-tolerant quantum hardware (not available this decade)** · gates KX-L3.*
96
 
 
 
 
 
97
  ## Phase 3 — cutting-edge + capstones
98
 
99
  ### KDRIVE — RL-control `[BUILT]`
@@ -148,3 +152,15 @@ active-learning acquisition — proposes the next most-informative CGYRO run fro
148
  open, citable fusion-ML benchmark suite — 3 tasks (CGYRO turbulence, MAST disruption, flux ROM) with real on-disk data, fixed reproducible splits, metrics, and KODEX baselines to beat. A community leaderboard starting point, not a private result; honest that it's small by mainstream-ML standards (pilot fusion-ML benchmarks).
149
  *provenance n/a · retired_by **community-standard fusion-ML benchmarks**.*
150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  **REAL quantum kernel** (PennyLane) — embeds real MAST disruption features into a quantum feature map and classifies on the fidelity kernel; runs on a simulator now, real QC hardware pluggable. MAST-disruption AUC **0.919** vs classical RBF 0.929 (ties — a validated null); a real, runnable quantum-ML pipeline on real fusion data.
95
  *provenance SIM · retired_by **fault-tolerant quantum hardware (not available this decade)** · gates KX-L3.*
96
 
97
+ ### KMIT — QMITIGATION `[BUILT]` ✦v0.3
98
+ **REAL quantum error mitigation** — zero-noise extrapolation (ZNE, global unitary folding) + inverse-confusion readout-error mitigation applied to the real KQUBIT H₂ VQE circuit (PennyLane default.mixed; sim now, real hardware pluggable). ZNE removes ~89% of the noise-induced energy error (44.4 → 5.0 mHa); readout mitigation cuts the measurement TV distance to ~0. Mitigation is the genuine NISQ tool TODAY — it recovers signal from noise, not a speedup. Honest: quantum's meaningful role in fusion is post-~2036.
99
+ *provenance SIM · retired_by **fault-tolerant quantum hardware (not available this decade)** · gates KX-L3.*
100
+
101
  ## Phase 3 — cutting-edge + capstones
102
 
103
  ### KDRIVE — RL-control `[BUILT]`
 
152
  open, citable fusion-ML benchmark suite — 3 tasks (CGYRO turbulence, MAST disruption, flux ROM) with real on-disk data, fixed reproducible splits, metrics, and KODEX baselines to beat. A community leaderboard starting point, not a private result; honest that it's small by mainstream-ML standards (pilot fusion-ML benchmarks).
153
  *provenance n/a · retired_by **community-standard fusion-ML benchmarks**.*
154
 
155
+ ### KMIND — FOUNDATION `[BUILT]` ✦v0.3
156
+ **whole-device foundation surrogate** — ONE shared-trunk multi-task neural net (per-domain input adapters → a shared plasma-state trunk → per-domain heads, ~67k params) trained JOINTLY across transport (KYRO), equilibrium (KORE), state (KFLOW) and disruption (KWARD) on the data those specialists use. Benchmarked head-by-head against a MATCHED single-task baseline on the same split: on the well-populated domains the shared representation shows **no negative transfer** (equilibrium slight positive, state/disruption neutral); transport is **data-starved (16 pts) and reported, not hidden**. MC-dropout uncertainty; per-domain trust gate (physical box for transport/equil, Mahalanobis for state/disrupt). The honest question a foundation model must answer — does one shared representation help or hurt each task? — answered with matched baselines.
157
+ *provenance SIM · retired_by **a device-scale multi-task foundation model on real multi-diagnostic data** · gates BR-L2-A1e, AC-16, AC-18, AC-20.*
158
+
159
+ ### KLINQ — QLINSOLVE `[BUILT]` ✦v0.3
160
+ **REAL quantum linear solver** — a variational quantum linear solver (VQLS) prepares the solution of a 4×4 reduced-MHD (discrete-Laplacian, SPD) linear system with a real quantum circuit (PennyLane; sim now, hardware pluggable), recovering the classical solution at fidelity ~1.0. Bundled with an honest fault-tolerant HHL resource estimate: a fusion-scale (N~1e6) sparse solve needs ~4e4 physical qubits — no advantage at real scale. Honest: quantum's meaningful role in fusion is post-~2036.
161
+ *provenance SIM · retired_by **fault-tolerant quantum hardware (not available this decade)** · gates KX-L3.*
162
+
163
+ ### KSCOUT — MF-CAMPAIGN `[BUILT]` ✦v0.3
164
+ **multi-fidelity Bayesian-optimization campaign manager** — extends KSEEK from a single next-point to a budget-constrained campaign that chooses which operating point AND which fidelity (reduced twin / μ=400 CGYRO / real-mass gold) to run next. Triage-then-escalate: cheap twin on every uncertain hotspot, escalate the most-uncertain to μ=400, reserve real-mass gold. Under a tight GPU-hour budget it reaches ~2.3× the mean truth-confidence of a naive all-μ=400 plan (which exhausts the budget and leaves most hotspots unexamined). Honest: fidelity correlations are assumptions (gold not yet run); GPU-hours only, no cost figures.
165
+ *provenance SIM · retired_by **the full multi-fidelity CGYRO campaign (twin + μ=400 + real-mass gold)** · gates BR-L2-A1e.*
166
+
benchmarks/benchmarks.json CHANGED
@@ -27,7 +27,7 @@
27
  "escapes": 0,
28
  "catch_rate": 1.0
29
  },
30
- "live_mpc_step_us": 155.4,
31
  "sourced": {
32
  "file": "track5_control/clamp_activation_stats.csv",
33
  "headline": "0 escapes / 150k steps / 3000 injected (AC-25); tracking <5%"
@@ -178,7 +178,7 @@
178
  "gates": [
179
  "KX-L3"
180
  ],
181
- "note": "REAL quantum dynamics \u2014 Trotterized time-evolution of a transverse-field Ising 'kinetic' Hamiltonian (PennyLane); the honest 1/n_steps cost curve for simulating plasma-like dynamics on a quantum computer. Runs on a simulator now, hardware pluggable",
182
  "available": true
183
  },
184
  "benchmark": {
@@ -200,7 +200,7 @@
200
  "active_backend": "default",
201
  "ran_on_real_hardware": false,
202
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
203
- "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
204
  },
205
  "verdict": "REAL Trotterized quantum dynamics: 1st-order error falls 1.34637 -> 0.03381 from 1 to 32 steps (~1/n) \u2014 the honest cost curve for simulating plasma-like Hamiltonian dynamics on a quantum computer. Runs on real hardware with KODEX_QC_BACKEND=ibm. No advantage at this size; a real, testable pipeline."
206
  },
@@ -613,6 +613,70 @@
613
  "note": "compact closure discovered from the 16/16 CGYRO map"
614
  }
615
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
616
  "KMAT": {
617
  "card": {
618
  "name": "KMAT",
@@ -649,6 +713,161 @@
649
  "note": "alloy screen BUILT; dpa/lifetime roadmap inside KMAT"
650
  }
651
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652
  "KOIL": {
653
  "card": {
654
  "name": "KOIL",
@@ -701,7 +920,7 @@
701
  "live_learned_surrogate": {
702
  "rel_l2_vs_analytic": 0.0035,
703
  "ensemble_cov90": 0.778,
704
- "infer_ms": 2.337,
705
  "grid": "16x16",
706
  "n_heldout": 120
707
  },
@@ -768,7 +987,7 @@
768
  "gates": [
769
  "KX-L3"
770
  ],
771
- "note": "REAL quantum-kernel classifier \u2014 embeds real MAST disruption features into a quantum feature map and classifies on the fidelity kernel (PennyLane); runs on a simulator now, real hardware pluggable. Honest: ties the classical kernel \u2014 a validated no-advantage result, but a real, runnable quantum-ML pipeline",
772
  "available": true
773
  },
774
  "benchmark": {
@@ -792,7 +1011,7 @@
792
  "active_backend": "default",
793
  "ran_on_real_hardware": false,
794
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
795
- "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
796
  },
797
  "verdict": "REAL quantum kernel classifies MAST disruptions at AUC 0.919 vs classical RBF 0.929 (Delta -0.010) \u2014 no advantage: a validated null, but a REAL runnable quantum-ML pipeline on real fusion data. Runs on hardware with KODEX_QC_BACKEND=ibm.",
798
  "caveats": [
@@ -817,7 +1036,7 @@
817
  "gates": [
818
  "KX-L3"
819
  ],
820
- "note": "REAL QAOA quantum optimizer \u2014 solves a combinatorial design QUBO on an actual quantum circuit (PennyLane); runs on a simulator now, real hardware pluggable, and you can plug in your own QUBO. Honest: standard ~0.7-1.0 approx ratio, no speedup at this size (~8-10 yr to advantage)",
821
  "available": true
822
  },
823
  "benchmark": {
@@ -842,7 +1061,7 @@
842
  "active_backend": "default",
843
  "ran_on_real_hardware": false,
844
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
845
- "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
846
  },
847
  "verdict": "REAL QAOA reaches 100% of the brute-force optimum (cut 6/6, p=2, 6 qubits) on the default backend \u2014 a working quantum optimizer, runnable on hardware with KODEX_QC_BACKEND=ibm. HONEST: no speedup vs classical at this size; advantage is ~8-10 yr out."
848
  },
@@ -864,7 +1083,7 @@
864
  "AC-43",
865
  "BR-SX-08"
866
  ],
867
- "note": "REAL fault-tolerant resource estimator \u2014 computes the classical<->quantum crossover N, the surface-code physical-qubit overhead, and the logical-qubit roadmap year for a fusion electronic-structure kernel (order-of-magnitude, literature-scaled). Verdict: no FT advantage this decade \u2014 the machine does not exist yet",
868
  "available": true
869
  },
870
  "benchmark": {
@@ -899,7 +1118,7 @@
899
  "AC-44",
900
  "KX-L3-A4"
901
  ],
902
- "note": "REAL variational quantum eigensolver (VQE) for a molecular Hamiltonian \u2014 a runnable quantum program (PennyLane): executes on a simulator now and on real quantum hardware when you plug in a backend. Honest: no quantum advantage yet (~8-10 yr out); the tooling + testing are real TODAY",
903
  "available": true
904
  },
905
  "benchmark": {
@@ -926,7 +1145,7 @@
926
  "active_backend": "default",
927
  "ran_on_real_hardware": false,
928
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
929
- "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
930
  },
931
  "verdict": "REAL VQE recovers the H2 ground state to 0.0002 mHa on the default backend (within 1.6 mHa chemical accuracy). Runs on real quantum hardware when you set KODEX_QC_BACKEND=ibm. HONEST: no quantum advantage this decade \u2014 the value now is a real, testable quantum pipeline, not a speedup."
932
  },
@@ -968,6 +1187,198 @@
968
  "caveat": "small seeding scan (few impurities); reduced 0-D radiation model"
969
  }
970
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
971
  "KSEEK": {
972
  "card": {
973
  "name": "KSEEK",
@@ -1022,7 +1433,7 @@
1022
  "gates": [
1023
  "HX-29"
1024
  ],
1025
- "note": "REAL quantum-metrology evaluation (PennyLane mixed-state) \u2014 GHZ interferometry: ideal gives Heisenberg (gain ~ N) scaling, but realistic dephasing (NV/SQUID/SERF reality) collapses it back to the standard quantum limit (~sqrt(N)). Honest null where fusion disruptions live",
1026
  "available": true
1027
  },
1028
  "benchmark": {
@@ -1091,7 +1502,7 @@
1091
  "active_backend": "default",
1092
  "ran_on_real_hardware": false,
1093
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
1094
- "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; this tooling makes the TESTING real and runnable TODAY, same code path"
1095
  },
1096
  "verdict": "REAL quantum-metrology computation: over N=2->8 the ideal GHZ gain grows 4.0x (Heisenberg ~ N), but with per-qubit dephasing (p=0.2) the dephased GHZ grows only 2.05x \u2014 essentially the SQL rate (2.01x, ~sqrt(N)). Dephasing ERASES the Heisenberg *scaling* to a bounded constant (gain turns over near N~9). HONEST NULL: no quantum-sensing advantage for fusion disruptions this decade \u2014 but a real, runnable metrology tool."
1097
  },
@@ -1112,7 +1523,7 @@
1112
  "gates": [
1113
  "KX-L3"
1114
  ],
1115
- "note": "tensor-network / low-rank ROM compression of the real CGYRO A1e flux database (classical MPS-style SVD; a many-body method and bridge to quantum kernels \u2014 NO quantum-advantage claim)",
1116
  "available": true
1117
  },
1118
  "benchmark": {
@@ -1263,9 +1674,9 @@
1263
  "map": "12 turbulent / 4 quiet (16/16 complete)"
1264
  },
1265
  "speed": {
1266
- "surrogate_ms_per_point": 0.329,
1267
  "cgyro_gpu_h_per_point_measured": 2.89,
1268
- "speedup_x_vs_cgyro": "3.2e+07",
1269
  "speedup_note": "ms inference vs GPU-hours for the CONVERGED flux value",
1270
  "fidelity": "representative mu=400; real-mass gold deferred"
1271
  },
 
27
  "escapes": 0,
28
  "catch_rate": 1.0
29
  },
30
+ "live_mpc_step_us": 77.8,
31
  "sourced": {
32
  "file": "track5_control/clamp_activation_stats.csv",
33
  "headline": "0 escapes / 150k steps / 3000 injected (AC-25); tracking <5%"
 
178
  "gates": [
179
  "KX-L3"
180
  ],
181
+ "note": "REAL quantum dynamics \u2014 Trotterized time-evolution of a transverse-field Ising 'kinetic' Hamiltonian (PennyLane); the honest 1/n_steps cost curve for simulating plasma-like dynamics on a quantum computer. Runs on a simulator now, hardware pluggable; quantum's role in fusion is post-~2036",
182
  "available": true
183
  },
184
  "benchmark": {
 
200
  "active_backend": "default",
201
  "ran_on_real_hardware": false,
202
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
203
+ "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
204
  },
205
  "verdict": "REAL Trotterized quantum dynamics: 1st-order error falls 1.34637 -> 0.03381 from 1 to 32 steps (~1/n) \u2014 the honest cost curve for simulating plasma-like Hamiltonian dynamics on a quantum computer. Runs on real hardware with KODEX_QC_BACKEND=ibm. No advantage at this size; a real, testable pipeline."
206
  },
 
613
  "note": "compact closure discovered from the 16/16 CGYRO map"
614
  }
615
  },
616
+ "KLINQ": {
617
+ "card": {
618
+ "name": "KLINQ",
619
+ "function": "QLINSOLVE",
620
+ "status": "BUILT",
621
+ "phase": 3,
622
+ "provenance": "SIM",
623
+ "retired_by": "fault-tolerant quantum hardware (not available this decade)",
624
+ "gates": [
625
+ "KX-L3"
626
+ ],
627
+ "note": "REAL quantum linear solver \u2014 a variational quantum linear solver (VQLS) prepares the solution of a small reduced-MHD linear system with a real quantum circuit (sim now, hardware pluggable), plus an honest fault-tolerant HHL resource estimate. No advantage at real scale; quantum's role in fusion is post-~2036",
628
+ "available": true
629
+ },
630
+ "benchmark": {
631
+ "member": "KLINQ",
632
+ "live_quantum_linear_solver": {
633
+ "problem": "solve A x = b for a 4x4 reduced-MHD Laplacian (SPD) with a real quantum circuit",
634
+ "method": "variational quantum linear solver (VQLS), global overlap cost, Powell optimization",
635
+ "framework": "PennyLane (sim now; Hadamard-test cost on real hardware, pluggable)",
636
+ "N": 4,
637
+ "n_qubits": 2,
638
+ "cost_final": 0.0,
639
+ "solution_fidelity_vs_classical": 1.0,
640
+ "residual_rel": 0.0,
641
+ "x_quantum": [
642
+ 0.8,
643
+ 0.6,
644
+ 0.4,
645
+ 0.2
646
+ ],
647
+ "x_classical": [
648
+ 0.8,
649
+ 0.6,
650
+ 0.4,
651
+ 0.2
652
+ ],
653
+ "ft_hhl_resource_estimate": {
654
+ "assumed_system": "N~1e+06 sparse SPD (reduced-MHD grid), kappa~1e+03",
655
+ "logical_qubits_needed": 31,
656
+ "physical_qubits_needed": "~4e+04",
657
+ "surface_code_phys_per_logical": 1250,
658
+ "roadmap_year_reach_logical": 2031,
659
+ "hardware_today": "~1e2-1e3 physical qubits, no error-corrected logical qubits",
660
+ "caveats": [
661
+ "HHL needs fault tolerance + sparse, well-conditioned A + efficient state prep, and returns |x> (aggregate readout), not the full vector",
662
+ "no fusion HHL advantage this decade \u2014 meaningful role post-~2036"
663
+ ]
664
+ },
665
+ "backend": {
666
+ "active_backend": "default",
667
+ "ran_on_real_hardware": false,
668
+ "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
669
+ "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
670
+ },
671
+ "verdict": "REAL variational quantum linear solver recovers the 4x4 reduced-MHD solve at solution fidelity 1.0 vs classical (rel-residual 0.0) \u2014 a runnable quantum linear solver TODAY. The fault-tolerant HHL route for a fusion-scale (N~1e6) solve needs ~31 logical -> ~4e+04 physical qubits (roadmap ~2031). HONEST: no advantage at real scale; quantum's meaningful role in fusion is post-~2036. Runs on hardware with KODEX_QC_BACKEND=ibm."
672
+ },
673
+ "caveats": [
674
+ "no quantum advantage \u2014 quantum's role in fusion is post-~2036",
675
+ "VQLS residual is read from the simulator here; on hardware it needs Hadamard tests and its cost landscape can have barren plateaus at scale",
676
+ "the 4x4 system is a toy; classical solves it instantly \u2014 the point is a real, honest, hardware-ready quantum pipeline, not a speedup"
677
+ ]
678
+ }
679
+ },
680
  "KMAT": {
681
  "card": {
682
  "name": "KMAT",
 
713
  "note": "alloy screen BUILT; dpa/lifetime roadmap inside KMAT"
714
  }
715
  },
716
+ "KMIND": {
717
+ "card": {
718
+ "name": "KMIND",
719
+ "function": "FOUNDATION",
720
+ "status": "BUILT",
721
+ "phase": 3,
722
+ "provenance": "SIM",
723
+ "retired_by": "a device-scale multi-task foundation model on real multi-diagnostic data",
724
+ "gates": [
725
+ "BR-L2-A1e",
726
+ "AC-16",
727
+ "AC-18",
728
+ "AC-20"
729
+ ],
730
+ "note": "whole-device foundation surrogate \u2014 one shared-trunk multi-task net across transport / equilibrium / state / disruption, trained jointly; reports shared-representation transfer honestly (incl. negative transfer)",
731
+ "available": true
732
+ },
733
+ "benchmark": {
734
+ "member": "KMIND",
735
+ "live_foundation": {
736
+ "architecture": "per-domain adapter (->32) + shared trunk (2x128, dropout 0.1) + per-domain head; 4 domains, joint training 300 steps",
737
+ "domains": [
738
+ "transport",
739
+ "equil",
740
+ "state",
741
+ "disrupt"
742
+ ],
743
+ "params": 66958,
744
+ "transfer_vs_single_task": {
745
+ "transport": {
746
+ "metric": "r2_log_Qtot",
747
+ "multitask": 0.577,
748
+ "single_task_baseline": 0.571,
749
+ "delta": 0.006,
750
+ "transfer": "data_starved",
751
+ "n_train": 12,
752
+ "n_test": 4
753
+ },
754
+ "equil": {
755
+ "metric": "rel_l2_field",
756
+ "multitask": 0.009,
757
+ "single_task_baseline": 0.0117,
758
+ "delta": -0.0027,
759
+ "transfer": "positive",
760
+ "n_train": 600,
761
+ "n_test": 200
762
+ },
763
+ "state": {
764
+ "metric": "norm_rmse",
765
+ "multitask": 0.0239,
766
+ "single_task_baseline": 0.0224,
767
+ "delta": 0.0015,
768
+ "transfer": "neutral",
769
+ "n_train": 1500,
770
+ "n_test": 500
771
+ },
772
+ "disrupt": {
773
+ "metric": "roc_auc",
774
+ "multitask": 0.99,
775
+ "single_task_baseline": 0.993,
776
+ "delta": -0.003,
777
+ "transfer": "neutral",
778
+ "n_train": 443,
779
+ "n_test": 148
780
+ }
781
+ },
782
+ "positive_transfer_domains": [
783
+ "equil"
784
+ ],
785
+ "negative_transfer_domains": [],
786
+ "neutral_transfer_domains": [
787
+ "state",
788
+ "disrupt"
789
+ ],
790
+ "data_starved_domains": [
791
+ "transport"
792
+ ],
793
+ "mc_dropout_predict_ms": 4.05,
794
+ "backend": "CPU, torch, MC-dropout UQ",
795
+ "verdict": "One shared trunk across 4 fusion domains, benchmarked head-by-head against a MATCHED single-task baseline on the same split. On the well-populated domains the shared representation is positive ['equil'], negative none, neutral ['state', 'disrupt'] \u2014 no negative transfer. ['transport'] is data-starved (16 pts) and not judged held-out. Trained on real on-disk data (CGYRO map / analytic equilibria / twin sensor snapshots / MAST shots) \u2014 an honest multi-task result, not a blanket win."
796
+ },
797
+ "caveats": [
798
+ "transport has only ~16 points, so its head is data-starved and high-variance (a real limit, reported not hidden)",
799
+ "uncertainty is an MC-dropout epistemic proxy, not a calibrated conformal interval",
800
+ "equilibrium targets are the analytic Solov'ev family (as in KORE); state targets are the analytic-twin sensor snapshots (as in KFLOW)"
801
+ ]
802
+ }
803
+ },
804
+ "KMIT": {
805
+ "card": {
806
+ "name": "KMIT",
807
+ "function": "QMITIGATION",
808
+ "status": "BUILT",
809
+ "phase": 2,
810
+ "provenance": "SIM",
811
+ "retired_by": "fault-tolerant quantum hardware (not available this decade)",
812
+ "gates": [
813
+ "KX-L3"
814
+ ],
815
+ "note": "REAL quantum error mitigation \u2014 zero-noise extrapolation (ZNE, unitary folding) + readout-error mitigation on a real fusion quantum circuit (the KQUBIT H2 VQE state). Mitigation is the genuine NISQ tool TODAY; it recovers signal from noise, not a speedup. Quantum's role in fusion is post-~2036",
816
+ "available": true
817
+ },
818
+ "benchmark": {
819
+ "member": "KMIT",
820
+ "live_error_mitigation": {
821
+ "problem": "mitigate a noisy H2 VQE expectation (the real KQUBIT circuit)",
822
+ "framework": "PennyLane default.mixed; ZNE via global unitary folding + linear extrapolation",
823
+ "zne": {
824
+ "exact_energy_Ha": -1.857275,
825
+ "ideal_noiseless_Ha": -1.857275,
826
+ "noisy_Ha": -1.812895,
827
+ "zne_mitigated_Ha": -1.852246,
828
+ "noise_scales_lambda": [
829
+ 1.0,
830
+ 3.0,
831
+ 5.0
832
+ ],
833
+ "energies_vs_lambda": [
834
+ -1.812895,
835
+ -1.725694,
836
+ -1.648692
837
+ ],
838
+ "error_noisy_mHa": 44.38,
839
+ "error_zne_mHa": 5.029,
840
+ "error_reduction_frac": 0.887,
841
+ "depolarizing_p": 0.04,
842
+ "backend": {
843
+ "active_backend": "default",
844
+ "ran_on_real_hardware": false,
845
+ "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
846
+ "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
847
+ }
848
+ },
849
+ "readout_mitigation": {
850
+ "readout_bitflip_p": 0.08,
851
+ "tv_distance_noisy": 0.1472,
852
+ "tv_distance_mitigated": 0.0,
853
+ "tv_reduction_frac": 1.0,
854
+ "method": "inverse confusion-matrix (linear) readout correction"
855
+ },
856
+ "backend": {
857
+ "active_backend": "default",
858
+ "ran_on_real_hardware": false,
859
+ "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
860
+ "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
861
+ },
862
+ "verdict": "REAL error mitigation on a fusion quantum circuit: ZNE cuts the noisy-energy error 44.38 -> 5.029 mHa (89% of the error removed) and inverse-confusion readout correction cuts the measurement TV distance 0.1472 -> 0.0 (100%). Mitigation is the REAL NISQ tool today \u2014 it recovers signal from noise. HONEST: it is NOT a speedup; quantum's meaningful role in fusion is post-~2036, and mitigation cost grows with noise. Runs on real hardware with KODEX_QC_BACKEND=ibm."
863
+ },
864
+ "caveats": [
865
+ "no quantum advantage \u2014 quantum's role in fusion is post-~2036",
866
+ "ZNE assumes a smooth noise->observable relation; it extrapolates, it does not eliminate noise, and its overhead grows as noise grows",
867
+ "readout mitigation uses a known confusion matrix; on hardware you must calibrate it"
868
+ ]
869
+ }
870
+ },
871
  "KOIL": {
872
  "card": {
873
  "name": "KOIL",
 
920
  "live_learned_surrogate": {
921
  "rel_l2_vs_analytic": 0.0035,
922
  "ensemble_cov90": 0.778,
923
+ "infer_ms": 0.318,
924
  "grid": "16x16",
925
  "n_heldout": 120
926
  },
 
987
  "gates": [
988
  "KX-L3"
989
  ],
990
+ "note": "REAL quantum-kernel classifier \u2014 embeds real MAST disruption features into a quantum feature map and classifies on the fidelity kernel (PennyLane); runs on a simulator now, real hardware pluggable. Honest: ties the classical kernel \u2014 a validated no-advantage result, but a real, runnable quantum-ML pipeline; role in fusion post-~2036",
991
  "available": true
992
  },
993
  "benchmark": {
 
1011
  "active_backend": "default",
1012
  "ran_on_real_hardware": false,
1013
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
1014
+ "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
1015
  },
1016
  "verdict": "REAL quantum kernel classifies MAST disruptions at AUC 0.919 vs classical RBF 0.929 (Delta -0.010) \u2014 no advantage: a validated null, but a REAL runnable quantum-ML pipeline on real fusion data. Runs on hardware with KODEX_QC_BACKEND=ibm.",
1017
  "caveats": [
 
1036
  "gates": [
1037
  "KX-L3"
1038
  ],
1039
+ "note": "REAL QAOA quantum optimizer \u2014 solves a combinatorial design QUBO on an actual quantum circuit (PennyLane); runs on a simulator now, real hardware pluggable, and you can plug in your own QUBO. Honest: standard ~0.7-1.0 approx ratio, no speedup at this size (advantage post-~2036)",
1040
  "available": true
1041
  },
1042
  "benchmark": {
 
1061
  "active_backend": "default",
1062
  "ran_on_real_hardware": false,
1063
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
1064
+ "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
1065
  },
1066
  "verdict": "REAL QAOA reaches 100% of the brute-force optimum (cut 6/6, p=2, 6 qubits) on the default backend \u2014 a working quantum optimizer, runnable on hardware with KODEX_QC_BACKEND=ibm. HONEST: no speedup vs classical at this size; advantage is ~8-10 yr out."
1067
  },
 
1083
  "AC-43",
1084
  "BR-SX-08"
1085
  ],
1086
+ "note": "REAL fault-tolerant resource estimator \u2014 computes the classical<->quantum crossover N, the surface-code physical-qubit overhead, and the logical-qubit roadmap year for a fusion electronic-structure kernel (order-of-magnitude, literature-scaled). Verdict: no FT advantage this decade \u2014 the machine does not exist yet; meaningful role post-~2036",
1087
  "available": true
1088
  },
1089
  "benchmark": {
 
1118
  "AC-44",
1119
  "KX-L3-A4"
1120
  ],
1121
+ "note": "REAL variational quantum eigensolver (VQE) for a molecular Hamiltonian \u2014 a runnable quantum program (PennyLane): executes on a simulator now and on real quantum hardware when you plug in a backend. Honest: no quantum advantage yet (~8-10 yr out); the tooling + testing are real TODAY \u2014 quantum's role in fusion is post-~2036",
1122
  "available": true
1123
  },
1124
  "benchmark": {
 
1145
  "active_backend": "default",
1146
  "ran_on_real_hardware": false,
1147
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
1148
+ "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
1149
  },
1150
  "verdict": "REAL VQE recovers the H2 ground state to 0.0002 mHa on the default backend (within 1.6 mHa chemical accuracy). Runs on real quantum hardware when you set KODEX_QC_BACKEND=ibm. HONEST: no quantum advantage this decade \u2014 the value now is a real, testable quantum pipeline, not a speedup."
1151
  },
 
1187
  "caveat": "small seeding scan (few impurities); reduced 0-D radiation model"
1188
  }
1189
  },
1190
+ "KSCOUT": {
1191
+ "card": {
1192
+ "name": "KSCOUT",
1193
+ "function": "MF-CAMPAIGN",
1194
+ "status": "BUILT",
1195
+ "phase": 3,
1196
+ "provenance": "SIM",
1197
+ "retired_by": "the full multi-fidelity CGYRO campaign (twin + mu=400 + real-mass gold)",
1198
+ "gates": [
1199
+ "BR-L2-A1e"
1200
+ ],
1201
+ "note": "multi-fidelity Bayesian-optimization campaign manager \u2014 extends KSEEK: chooses which operating point AND which fidelity (reduced twin / mu=400 CGYRO / real-mass gold) to run next, greedily maximizing truth-weighted information per GPU-hour under a budget",
1202
+ "available": true
1203
+ },
1204
+ "benchmark": {
1205
+ "member": "KSCOUT",
1206
+ "live_mf_campaign": {
1207
+ "source": "KYRO GP over the completed 16-pt CGYRO A1e map",
1208
+ "budget_gpu_h": 15.0,
1209
+ "target_hotspots": 16,
1210
+ "policy": "twin-triage every hotspot, escalate most-uncertain to mu=400, reserve gold",
1211
+ "fidelities": {
1212
+ "twin": {
1213
+ "gpu_h": 0.0,
1214
+ "rho": 0.55,
1215
+ "desc": "reduced analytic twin (near-free triage)"
1216
+ },
1217
+ "cgyro_mu400": {
1218
+ "gpu_h": 2.89,
1219
+ "rho": 0.9,
1220
+ "desc": "CGYRO representative mu=400 (measured GPU-h)"
1221
+ },
1222
+ "gold_mu3672": {
1223
+ "gpu_h": 28.9,
1224
+ "rho": 1.0,
1225
+ "desc": "CGYRO real-mass gold (est. ~10x mu=400; not yet run)"
1226
+ }
1227
+ },
1228
+ "multi_fidelity_plan": [
1229
+ {
1230
+ "a_LT": 3.25,
1231
+ "shear": 1.4,
1232
+ "fidelity": "cgyro_mu400",
1233
+ "gpu_h": 2.99,
1234
+ "gp_std": 0.5041,
1235
+ "truth_confidence_rho": 0.9
1236
+ },
1237
+ {
1238
+ "a_LT": 2.25,
1239
+ "shear": 1.4,
1240
+ "fidelity": "cgyro_mu400",
1241
+ "gpu_h": 2.99,
1242
+ "gp_std": 0.5041,
1243
+ "truth_confidence_rho": 0.9
1244
+ },
1245
+ {
1246
+ "a_LT": 3.25,
1247
+ "shear": 0.6,
1248
+ "fidelity": "cgyro_mu400",
1249
+ "gpu_h": 2.99,
1250
+ "gp_std": 0.5041,
1251
+ "truth_confidence_rho": 0.9
1252
+ },
1253
+ {
1254
+ "a_LT": 2.25,
1255
+ "shear": 0.6,
1256
+ "fidelity": "cgyro_mu400",
1257
+ "gpu_h": 2.99,
1258
+ "gp_std": 0.5041,
1259
+ "truth_confidence_rho": 0.9
1260
+ },
1261
+ {
1262
+ "a_LT": 3.25,
1263
+ "shear": 1.0,
1264
+ "fidelity": "twin",
1265
+ "gpu_h": 0.1,
1266
+ "gp_std": 0.4831,
1267
+ "truth_confidence_rho": 0.55
1268
+ },
1269
+ {
1270
+ "a_LT": 2.25,
1271
+ "shear": 1.0,
1272
+ "fidelity": "twin",
1273
+ "gpu_h": 0.1,
1274
+ "gp_std": 0.4831,
1275
+ "truth_confidence_rho": 0.55
1276
+ },
1277
+ {
1278
+ "a_LT": 2.75,
1279
+ "shear": 0.6,
1280
+ "fidelity": "twin",
1281
+ "gpu_h": 0.1,
1282
+ "gp_std": 0.4831,
1283
+ "truth_confidence_rho": 0.55
1284
+ },
1285
+ {
1286
+ "a_LT": 2.75,
1287
+ "shear": 1.4,
1288
+ "fidelity": "twin",
1289
+ "gpu_h": 0.1,
1290
+ "gp_std": 0.4831,
1291
+ "truth_confidence_rho": 0.55
1292
+ },
1293
+ {
1294
+ "a_LT": 2.75,
1295
+ "shear": 1.0,
1296
+ "fidelity": "twin",
1297
+ "gpu_h": 0.1,
1298
+ "gp_std": 0.4623,
1299
+ "truth_confidence_rho": 0.55
1300
+ },
1301
+ {
1302
+ "a_LT": 2.25,
1303
+ "shear": 0.4,
1304
+ "fidelity": "twin",
1305
+ "gpu_h": 0.1,
1306
+ "gp_std": 0.3838,
1307
+ "truth_confidence_rho": 0.55
1308
+ },
1309
+ {
1310
+ "a_LT": 2.25,
1311
+ "shear": 1.6,
1312
+ "fidelity": "twin",
1313
+ "gpu_h": 0.1,
1314
+ "gp_std": 0.3838,
1315
+ "truth_confidence_rho": 0.55
1316
+ },
1317
+ {
1318
+ "a_LT": 3.25,
1319
+ "shear": 1.6,
1320
+ "fidelity": "twin",
1321
+ "gpu_h": 0.1,
1322
+ "gp_std": 0.3838,
1323
+ "truth_confidence_rho": 0.55
1324
+ },
1325
+ {
1326
+ "a_LT": 3.25,
1327
+ "shear": 0.4,
1328
+ "fidelity": "twin",
1329
+ "gpu_h": 0.1,
1330
+ "gp_std": 0.3838,
1331
+ "truth_confidence_rho": 0.55
1332
+ },
1333
+ {
1334
+ "a_LT": 2.0,
1335
+ "shear": 1.4,
1336
+ "fidelity": "twin",
1337
+ "gpu_h": 0.1,
1338
+ "gp_std": 0.3838,
1339
+ "truth_confidence_rho": 0.55
1340
+ },
1341
+ {
1342
+ "a_LT": 3.5,
1343
+ "shear": 1.4,
1344
+ "fidelity": "twin",
1345
+ "gpu_h": 0.1,
1346
+ "gp_std": 0.3838,
1347
+ "truth_confidence_rho": 0.55
1348
+ },
1349
+ {
1350
+ "a_LT": 2.0,
1351
+ "shear": 0.6,
1352
+ "fidelity": "twin",
1353
+ "gpu_h": 0.1,
1354
+ "gp_std": 0.3838,
1355
+ "truth_confidence_rho": 0.55
1356
+ }
1357
+ ],
1358
+ "mf_runs": 16,
1359
+ "mf_gpu_h_used": 13.56,
1360
+ "mf_runs_by_fidelity": {
1361
+ "twin": 12,
1362
+ "cgyro_mu400": 4,
1363
+ "gold_mu3672": 0
1364
+ },
1365
+ "mf_mean_confidence_rho": 0.638,
1366
+ "baseline_all_mu400": {
1367
+ "n_runs": 5,
1368
+ "gpu_h_used": 14.95,
1369
+ "mean_confidence_rho": 0.281,
1370
+ "unvisited_hotspots": 11
1371
+ },
1372
+ "mf_confidence_gain_x_vs_all_mu400": 2.27,
1373
+ "verdict": "Under a tight 15.0 GPU-h budget across 16 uncertain operating points, the multi-fidelity policy triages ALL 16 with cheap twin runs and escalates 4 to mu=400 (0 to real-mass gold), reaching mean truth-confidence rho 0.638 \u2014 vs 0.281 for a naive all-mu=400 plan that exhausts the budget after 5 points and leaves 11 hotspots unexamined (2.27x). A real cost-aware campaign manager: look everywhere cheaply, spend the expensive fidelity where KYRO is least sure."
1374
+ },
1375
+ "caveats": [
1376
+ "the per-fidelity rho (correlation-with-truth) values are ASSUMPTIONS \u2014 the real-mass gold has not been run \u2014 so this is a planning heuristic, not a measured speedup; the advantage holds only while budget < hotspots x mu=400 cost",
1377
+ "GP std comes from only 16 points (directional, like KSEEK)",
1378
+ "GPU-hours only; no compute-cost figures (product-econ rule)"
1379
+ ]
1380
+ }
1381
+ },
1382
  "KSEEK": {
1383
  "card": {
1384
  "name": "KSEEK",
 
1433
  "gates": [
1434
  "HX-29"
1435
  ],
1436
+ "note": "REAL quantum-metrology evaluation (PennyLane mixed-state) \u2014 GHZ interferometry: ideal gives Heisenberg (gain ~ N) scaling, but realistic dephasing (NV/SQUID/SERF reality) collapses it back to the standard quantum limit (~sqrt(N)). Honest null where fusion disruptions live; quantum's role in fusion is post-~2036",
1437
  "available": true
1438
  },
1439
  "benchmark": {
 
1502
  "active_backend": "default",
1503
  "ran_on_real_hardware": false,
1504
  "how_to_use_real_qc": "set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum token> to run this exact circuit on real quantum hardware",
1505
+ "honest_timeline": "fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out \u2014 a meaningful role in fusion only after ~2036; this tooling makes the TESTING real and runnable TODAY, same code path"
1506
  },
1507
  "verdict": "REAL quantum-metrology computation: over N=2->8 the ideal GHZ gain grows 4.0x (Heisenberg ~ N), but with per-qubit dephasing (p=0.2) the dephased GHZ grows only 2.05x \u2014 essentially the SQL rate (2.01x, ~sqrt(N)). Dephasing ERASES the Heisenberg *scaling* to a bounded constant (gain turns over near N~9). HONEST NULL: no quantum-sensing advantage for fusion disruptions this decade \u2014 but a real, runnable metrology tool."
1508
  },
 
1523
  "gates": [
1524
  "KX-L3"
1525
  ],
1526
+ "note": "tensor-network / low-rank ROM compression of the real CGYRO A1e flux database (classical MPS-style SVD; a many-body method and bridge to quantum kernels \u2014 NO quantum-advantage claim; quantum's role in fusion is post-~2036)",
1527
  "available": true
1528
  },
1529
  "benchmark": {
 
1674
  "map": "12 turbulent / 4 quiet (16/16 complete)"
1675
  },
1676
  "speed": {
1677
+ "surrogate_ms_per_point": 0.257,
1678
  "cgyro_gpu_h_per_point_measured": 2.89,
1679
+ "speedup_x_vs_cgyro": "4.1e+07",
1680
  "speedup_note": "ms inference vs GPU-hours for the CONVERGED flux value",
1681
  "fidelity": "representative mu=400; real-mass gold deferred"
1682
  },
benchmarks/run_all.py CHANGED
@@ -181,6 +181,31 @@ def _headline(name, b):
181
  r = b.get("live_impurity_seeding", {})
182
  return (f"impurity-seeding radiation evaluator: {r.get('n_impurities')} impurities "
183
  f"({', '.join(r.get('impurities', []))}); least core dilution = {r.get('least_core_dilution_impurity')}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  return b.get("note", b.get("headline", "roadmap"))
185
 
186
 
 
181
  r = b.get("live_impurity_seeding", {})
182
  return (f"impurity-seeding radiation evaluator: {r.get('n_impurities')} impurities "
183
  f"({', '.join(r.get('impurities', []))}); least core dilution = {r.get('least_core_dilution_impurity')}")
184
+ if name == "KMIND":
185
+ lf = b.get("live_foundation", {})
186
+ pos = lf.get("positive_transfer_domains", []); neg = lf.get("negative_transfer_domains", [])
187
+ neu = lf.get("neutral_transfer_domains", []); st = lf.get("data_starved_domains", [])
188
+ return (f"**foundation model**: one shared trunk across {len(lf.get('domains', []))} domains "
189
+ f"({lf.get('params', '?')} params); transfer vs matched single-task — pos {pos or 'none'}, "
190
+ f"neg {neg or 'none'}, neutral {neu or 'none'}"
191
+ + (" (transport data-starved)" if st else "") + " — honest multi-task result")
192
+ if name == "KMIT":
193
+ m = b.get("live_error_mitigation", {}); z = m.get("zne", {}); ro = m.get("readout_mitigation", {})
194
+ return (f"**REAL error mitigation**: ZNE cuts H2 energy error {z.get('error_noisy_mHa')}→"
195
+ f"{z.get('error_zne_mHa')} mHa ({z.get('error_reduction_frac')} removed); readout TV "
196
+ f"{ro.get('tv_distance_noisy')}→{ro.get('tv_distance_mitigated')} — real NISQ tool today, "
197
+ f"role post-~2036")
198
+ if name == "KLINQ":
199
+ q = b.get("live_quantum_linear_solver", {}); hhl = q.get("ft_hhl_resource_estimate", {})
200
+ return (f"**REAL quantum linear solver** (VQLS): 4×4 reduced-MHD solve fidelity "
201
+ f"{q.get('solution_fidelity_vs_classical')} vs classical (rel-resid {q.get('residual_rel')}); "
202
+ f"FT-HHL {hhl.get('physical_qubits_needed')} phys qubits — no advantage, role post-~2036")
203
+ if name == "KSCOUT":
204
+ c = b.get("live_mf_campaign", {}); base = c.get("baseline_all_mu400", {})
205
+ return (f"**multi-fidelity campaign**: tight {c.get('budget_gpu_h')} GPU-h over "
206
+ f"{c.get('target_hotspots')} hotspots → mean confidence ρ {c.get('mf_mean_confidence_rho')} "
207
+ f"vs {base.get('mean_confidence_rho')} all-μ=400 "
208
+ f"({c.get('mf_confidence_gain_x_vs_all_mu400')}×); triage-then-escalate")
209
  return b.get("note", b.get("headline", "roadmap"))
210
 
211
 
codemeta.json CHANGED
@@ -2,8 +2,8 @@
2
  "@context": "https://doi.org/10.5063/schema/codemeta-2.0",
3
  "@type": "SoftwareSourceCode",
4
  "name": "KODEX: the Kronos Family of Codes",
5
- "version": "0.1.0",
6
- "dateModified": "2026-09-10",
7
  "license": "https://spdx.org/licenses/Apache-2.0",
8
  "codeRepository": "https://github.com/KronosFE/kronos-ml",
9
  "url": "https://kronosfusionenergy.com/kodex",
 
2
  "@context": "https://doi.org/10.5063/schema/codemeta-2.0",
3
  "@type": "SoftwareSourceCode",
4
  "name": "KODEX: the Kronos Family of Codes",
5
+ "version": "0.3.0",
6
+ "dateModified": "2026-09-29",
7
  "license": "https://spdx.org/licenses/Apache-2.0",
8
  "codeRepository": "https://github.com/KronosFE/kronos-ml",
9
  "url": "https://kronosfusionenergy.com/kodex",
kronos_ml/members/__init__.py CHANGED
@@ -16,3 +16,5 @@ from . import advanced # noqa: F401 KLAW, KDRIVE, KGEN, KFUEL
16
  from . import capstone # noqa: F401 KFORGE, KPILOT
17
  from . import neutronics # noqa: F401 KBREED, KFLUX
18
  from . import roadmap # noqa: F401 KHEAT, KEDGE, KRAD, KECON
 
 
 
16
  from . import capstone # noqa: F401 KFORGE, KPILOT
17
  from . import neutronics # noqa: F401 KBREED, KFLUX
18
  from . import roadmap # noqa: F401 KHEAT, KEDGE, KRAD, KECON
19
+ from . import foundation # noqa: F401 KMIND (v0.3.0)
20
+ from . import quantum_v3 # noqa: F401 KMIT, KLINQ (v0.3.0)
kronos_ml/members/advanced.py CHANGED
@@ -358,3 +358,136 @@ class KBENCH(Surrogate):
358
  "ROM) with real on-disk data + reproducible KODEX baselines — a community "
359
  "leaderboard starting point, not a private result")},
360
  "caveat": "small by mainstream-ML standards (CGYRO = 16 pts); honest pilot fusion-ML benchmarks"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  "ROM) with real on-disk data + reproducible KODEX baselines — a community "
359
  "leaderboard starting point, not a private result")},
360
  "caveat": "small by mainstream-ML standards (CGYRO = 16 pts); honest pilot fusion-ML benchmarks"}
361
+
362
+
363
+ # ------------------------------------------------------------------ KSCOUT
364
+ @register
365
+ class KSCOUT(Surrogate):
366
+ name = "KSCOUT"; function = "MF-CAMPAIGN"; phase = 3; status = "BUILT"
367
+ provenance = "SIM"
368
+ retired_by = "the full multi-fidelity CGYRO campaign (twin + mu=400 + real-mass gold)"
369
+ real_codes = ("multi-fidelity Bayesian optimization", "cost-aware acquisition")
370
+ gates = ("BR-L2-A1e",)
371
+ note = ("multi-fidelity Bayesian-optimization campaign manager — extends KSEEK: chooses which "
372
+ "operating point AND which fidelity (reduced twin / mu=400 CGYRO / real-mass gold) to "
373
+ "run next, greedily maximizing truth-weighted information per GPU-hour under a budget")
374
+
375
+ _BOX = ((2.0, 3.5), (0.4, 1.6)) # a_LT, shear (matches KYRO / KSEEK)
376
+ _C0 = 0.10 # fixed per-run setup overhead (GPU-h equiv.)
377
+ _HOTSPOTS = 16 # target uncertain locations for a campaign
378
+ # honest fidelity model: measured mu=400 cost; twin ~free; gold ~10x mu=400 (estimate, not yet run).
379
+ # rho = ASSUMED correlation-with-truth per fidelity (gold=1 by definition); labelled as assumptions.
380
+ _FIDELITIES = {
381
+ "twin": {"gpu_h": 0.0, "rho": 0.55, "desc": "reduced analytic twin (near-free triage)"},
382
+ "cgyro_mu400": {"gpu_h": 2.89, "rho": 0.90, "desc": "CGYRO representative mu=400 (measured GPU-h)"},
383
+ "gold_mu3672": {"gpu_h": 28.9, "rho": 1.00, "desc": "CGYRO real-mass gold (est. ~10x mu=400; not yet run)"},
384
+ }
385
+
386
+ def _grid(self, n=31):
387
+ a = np.linspace(*self._BOX[0], n); s = np.linspace(*self._BOX[1], n)
388
+ A, S = np.meshgrid(a, s)
389
+ return np.c_[A.ravel(), S.ravel()]
390
+
391
+ def _hotspots(self, n_hotspots, min_sep=0.16):
392
+ """The n most-uncertain operating points (KYRO GP std), min-separated + away from data."""
393
+ gp = get("KYRO")._fit()
394
+ G = self._grid()
395
+ _, std = gp.predict(G); std = np.asarray(std).ravel()
396
+ Xtr = data.cgyro_flux_map_final()[["a_LT", "shear"]].to_numpy(float)
397
+ span = np.array([self._BOX[0][1] - self._BOX[0][0], self._BOX[1][1] - self._BOX[1][0]])
398
+ picks = []
399
+ for idx in np.argsort(-std):
400
+ g = G[idx]
401
+ d_tr = np.linalg.norm((g - Xtr) / span, axis=1).min()
402
+ d_ch = min([np.linalg.norm((g - c[0]) / span) for c in picks], default=9.0)
403
+ if min(d_tr, d_ch) < min_sep:
404
+ continue
405
+ picks.append((g, float(std[idx])))
406
+ if len(picks) >= n_hotspots:
407
+ break
408
+ return picks
409
+
410
+ def _cost(self, fid):
411
+ return self._FIDELITIES[fid]["gpu_h"] + self._C0
412
+
413
+ def _plan(self, budget, n_hotspots=None):
414
+ """Triage-and-escalate: twin-triage every hotspot, then escalate the most-uncertain to
415
+ mu=400, then the single most-critical to real-mass gold — all within the GPU-h budget."""
416
+ n_hotspots = n_hotspots or self._HOTSPOTS
417
+ hs = self._hotspots(n_hotspots) # sorted by std desc
418
+ c_t, c_m, c_g = (self._cost("twin"), self._cost("cgyro_mu400"), self._cost("gold_mu3672"))
419
+ tiers = [None] * len(hs); used = 0.0
420
+ # tier 1 — cheap twin triage on as many hotspots as the budget allows (highest std first)
421
+ for i in range(len(hs)):
422
+ if used + c_t <= budget + 1e-9:
423
+ tiers[i] = "twin"; used += c_t
424
+ # tier 2 — escalate the single most-uncertain to real-mass gold if affordable
425
+ if tiers and tiers[0] == "twin" and used + c_g <= budget + 1e-9:
426
+ tiers[0] = "gold_mu3672"; used += c_g
427
+ # tier 3 — escalate the next most-uncertain to mu=400 while budget remains
428
+ for i in range(len(hs)):
429
+ if tiers[i] == "twin" and used + c_m <= budget + 1e-9:
430
+ tiers[i] = "cgyro_mu400"; used += c_m
431
+ plan = []
432
+ for (g, s), tier in zip(hs, tiers):
433
+ if tier is None:
434
+ continue
435
+ plan.append({"a_LT": round(float(g[0]), 3), "shear": round(float(g[1]), 3),
436
+ "fidelity": tier, "gpu_h": round(self._cost(tier), 2),
437
+ "gp_std": round(float(s), 4),
438
+ "truth_confidence_rho": self._FIDELITIES[tier]["rho"]})
439
+ return plan, round(used, 2), hs
440
+
441
+ def _mean_confidence(self, plan, n_hotspots):
442
+ """Mean truth-confidence (rho) achieved across ALL target hotspots (unvisited = 0)."""
443
+ return round(sum(p["truth_confidence_rho"] for p in plan) / n_hotspots, 3)
444
+
445
+ def _baseline_all_mu400(self, budget, n_hotspots):
446
+ """Naive baseline: spend the whole budget at mu=400 on the highest-std hotspots."""
447
+ c_m = self._cost("cgyro_mu400")
448
+ n = min(n_hotspots, int((budget + 1e-9) // c_m))
449
+ return {"n_runs": n, "gpu_h_used": round(n * c_m, 2),
450
+ "mean_confidence_rho": round(n * self._FIDELITIES["cgyro_mu400"]["rho"] / n_hotspots, 3),
451
+ "unvisited_hotspots": n_hotspots - n}
452
+
453
+ def _predict(self, x):
454
+ """x = GPU-hour budget (float) -> the recommended multi-fidelity campaign plan."""
455
+ budget = float(np.ravel(np.asarray(x, float))[0]) if x is not None else 15.0
456
+ plan, used, _ = self._plan(budget)
457
+ by_fid = {f: sum(1 for p in plan if p["fidelity"] == f) for f in self._FIDELITIES}
458
+ return Prediction(plan, None, True,
459
+ note=f"multi-fidelity campaign: {len(plan)} runs {by_fid}, {used} GPU-h of {budget}")
460
+
461
+ def benchmark(self):
462
+ budget = 15.0 # tight budget: mu=400 can't cover every hotspot
463
+ n = self._HOTSPOTS
464
+ plan, used, hs = self._plan(budget, n)
465
+ by_fid = {f: sum(1 for p in plan if p["fidelity"] == f) for f in self._FIDELITIES}
466
+ mf_conf = self._mean_confidence(plan, n)
467
+ base = self._baseline_all_mu400(budget, n)
468
+ ratio = round(mf_conf / base["mean_confidence_rho"], 2) if base["mean_confidence_rho"] > 1e-9 else None
469
+ return {"member": self.name,
470
+ "live_mf_campaign": {
471
+ "source": "KYRO GP over the completed 16-pt CGYRO A1e map",
472
+ "budget_gpu_h": budget, "target_hotspots": n,
473
+ "policy": "twin-triage every hotspot, escalate most-uncertain to mu=400, reserve gold",
474
+ "fidelities": {k: {kk: v[kk] for kk in ("gpu_h", "rho", "desc")}
475
+ for k, v in self._FIDELITIES.items()},
476
+ "multi_fidelity_plan": plan,
477
+ "mf_runs": len(plan), "mf_gpu_h_used": used, "mf_runs_by_fidelity": by_fid,
478
+ "mf_mean_confidence_rho": mf_conf,
479
+ "baseline_all_mu400": base,
480
+ "mf_confidence_gain_x_vs_all_mu400": ratio,
481
+ "verdict": (f"Under a tight {budget} GPU-h budget across {n} uncertain operating points, the "
482
+ f"multi-fidelity policy triages ALL {n} with cheap twin runs and escalates "
483
+ f"{by_fid['cgyro_mu400']} to mu=400 ({by_fid['gold_mu3672']} to real-mass gold), "
484
+ f"reaching mean truth-confidence rho {mf_conf} — vs {base['mean_confidence_rho']} "
485
+ f"for a naive all-mu=400 plan that exhausts the budget after {base['n_runs']} "
486
+ f"points and leaves {base['unvisited_hotspots']} hotspots unexamined ({ratio}x). "
487
+ f"A real cost-aware campaign manager: look everywhere cheaply, spend the "
488
+ f"expensive fidelity where KYRO is least sure.")},
489
+ "caveats": ["the per-fidelity rho (correlation-with-truth) values are ASSUMPTIONS — the "
490
+ "real-mass gold has not been run — so this is a planning heuristic, not a "
491
+ "measured speedup; the advantage holds only while budget < hotspots x mu=400 cost",
492
+ "GP std comes from only 16 points (directional, like KSEEK)",
493
+ "GPU-hours only; no compute-cost figures (product-econ rule)"]}
kronos_ml/members/foundation.py ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """KMIND — whole-device foundation surrogate (shared-trunk multi-task model).
2
+
3
+ ONE shared plasma-state trunk feeds four domain heads — transport (KYRO),
4
+ equilibrium (KORE), state (KFLOW) and disruption (KWARD) — trained JOINTLY on the
5
+ on-disk data those specialists use. Per-domain input adapters project each
6
+ domain's heterogeneous inputs into a common embedding; the shared trunk learns a
7
+ representation every head reads; per-domain heads emit the domain output.
8
+
9
+ The honest question a foundation model has to answer: does forcing four fusion
10
+ sub-problems through ONE shared representation help or hurt each of them vs a
11
+ matched single-task specialist? `benchmark()` trains the multi-task model AND a
12
+ matched single-task baseline per domain on the SAME split and reports the
13
+ transfer — positive OR negative — in each domain's own metric. No hype: a shared
14
+ representation that hurts a task is reported as hurting it.
15
+
16
+ CPU-only, deterministic (fixed seed), torch (lazy import). Uncertainty is an
17
+ MC-dropout epistemic proxy; the per-domain in_domain gate is a Mahalanobis
18
+ distance to that domain's training inputs.
19
+ """
20
+ from __future__ import annotations
21
+
22
+ import time
23
+ import numpy as np
24
+
25
+ from .. import register, get
26
+ from ..base import Surrogate, Prediction
27
+ from .. import uq, metrics, data
28
+ from .._torch import torch
29
+ from .equil import _field, _A, _K, _D
30
+
31
+ _D_EMB = 32 # shared embedding width (adapter output)
32
+ _H = 128 # shared trunk width
33
+ _DROP = 0.1 # dropout (also the MC-dropout head)
34
+ _STEPS = 300 # joint / baseline training steps (same for fairness)
35
+ _BATCH = 64
36
+ _MC = 30 # MC-dropout passes for predictive std
37
+ _DOMAINS = ("transport", "equil", "state", "disrupt")
38
+
39
+
40
+ # ---- per-domain data builders (all read-only, on-disk) -------------------
41
+
42
+ def _transport_xy():
43
+ df = data.cgyro_flux_map_final()
44
+ X = df[["a_LT", "shear"]].to_numpy(float)
45
+ y = np.log10(np.clip(df.Q_tot.to_numpy(float), 0, None) + 1e-4).reshape(-1, 1)
46
+ return X, y
47
+
48
+
49
+ def _equil_xy(n=800, seed=uq.SEED):
50
+ rng = np.random.default_rng(seed)
51
+ P = np.c_[rng.uniform(*_A, n), rng.uniform(*_K, n), rng.uniform(*_D, n)]
52
+ Y = np.array([_field(*p) for p in P], float)
53
+ return P.astype(float), Y
54
+
55
+
56
+ def _state_xy(n=2000, seed=uq.SEED):
57
+ z = data.gnn_snapshots()
58
+ Xobs = np.nan_to_num(np.asarray(z["Xn_obs"], float))
59
+ Yclean = np.nan_to_num(np.asarray(z["Xn_clean"], float))
60
+ if len(Xobs) > n: # deterministic subsample for speed
61
+ idx = np.random.default_rng(seed).choice(len(Xobs), n, replace=False)
62
+ Xobs, Yclean = Xobs[idx], Yclean[idx]
63
+ return Xobs, Yclean
64
+
65
+
66
+ def _disrupt_xy():
67
+ X, y, _ = get("KWARD")._real_features()
68
+ return np.asarray(X, float), np.asarray(y, int).reshape(-1, 1)
69
+
70
+
71
+ _BUILDERS = {"transport": _transport_xy, "equil": _equil_xy,
72
+ "state": _state_xy, "disrupt": _disrupt_xy}
73
+ _KIND = {"transport": "reg", "equil": "reg", "state": "reg", "disrupt": "cls"}
74
+ # physical in-domain boxes for the low-D parametric domains (match KYRO / KORE);
75
+ # the high-D domains (state, disrupt) use a Mahalanobis gate on training inputs
76
+ _BOX = {"transport": ((2.0, 3.5), (0.4, 1.6)),
77
+ "equil": ((0.8, 1.2), (1.5, 2.5), (-0.5, 0.5))}
78
+
79
+
80
+ def _spec(name, test_frac=0.25, seed=uq.SEED):
81
+ """Build a domain spec: standardized train/test tensors + inversion stats + gate."""
82
+ X, Y = _BUILDERS[name]()
83
+ n = len(X)
84
+ rng = np.random.default_rng(seed + hash(name) % 1000)
85
+ perm = rng.permutation(n)
86
+ nte = max(2, int(round(test_frac * n)))
87
+ te, tr = perm[:nte], perm[nte:]
88
+ Xtr, Xte, Ytr, Yte = X[tr], X[te], Y[tr], Y[te]
89
+ xmu, xsd = Xtr.mean(0), Xtr.std(0) + 1e-8
90
+ kind = _KIND[name]
91
+ if kind == "reg":
92
+ ymu, ysd = Ytr.mean(0), Ytr.std(0) + 1e-8
93
+ else:
94
+ ymu, ysd = np.zeros(Y.shape[1]), np.ones(Y.shape[1]) # raw {0,1} labels
95
+ gate = None if name in _BOX else uq.MahalanobisGate(0.05).fit(Xtr)
96
+ return {"name": name, "kind": kind, "in_dim": X.shape[1], "out_dim": Y.shape[1],
97
+ "Xtr": Xtr, "Xte": Xte, "Ytr": Ytr, "Yte": Yte,
98
+ "xmu": xmu, "xsd": xsd, "ymu": ymu, "ysd": ysd, "gate": gate, "n": n}
99
+
100
+
101
+ def _in_domain(sp, x_raw):
102
+ """Per-domain trust gate, queried on RAW inputs: a physical box for the low-D
103
+ parametric domains (transport/equil), Mahalanobis distance for the rest."""
104
+ x = np.asarray(x_raw, float).ravel()
105
+ if sp["name"] in _BOX:
106
+ b = _BOX[sp["name"]]
107
+ return bool(len(x) >= len(b) and all(lo <= x[i] <= hi for i, (lo, hi) in enumerate(b)))
108
+ return bool(sp["gate"].in_domain(x.reshape(1, -1)))
109
+
110
+
111
+ def _stdx(sp, X):
112
+ return ((np.atleast_2d(np.asarray(X, float)) - sp["xmu"]) / sp["xsd"]).astype("float32")
113
+
114
+
115
+ def _stdy(sp, Y):
116
+ return ((np.asarray(Y, float) - sp["ymu"]) / sp["ysd"]).astype("float32")
117
+
118
+
119
+ def _invy(sp, Yn):
120
+ return np.asarray(Yn, float) * sp["ysd"] + sp["ymu"]
121
+
122
+
123
+ # ---- the shared-trunk multi-task network ---------------------------------
124
+
125
+ def _build_net(specs, seed=uq.SEED):
126
+ t = torch(); t.set_num_threads(1); t.manual_seed(seed) # single-thread -> reproducible
127
+ nn = t.nn
128
+
129
+ class MultiTask(nn.Module):
130
+ def __init__(self):
131
+ super().__init__()
132
+ self.adapters = nn.ModuleDict({
133
+ s["name"]: nn.Sequential(nn.Linear(s["in_dim"], _D_EMB), nn.SiLU())
134
+ for s in specs})
135
+ self.trunk = nn.Sequential(
136
+ nn.Linear(_D_EMB, _H), nn.SiLU(), nn.Dropout(_DROP),
137
+ nn.Linear(_H, _H), nn.SiLU(), nn.Dropout(_DROP))
138
+ self.heads = nn.ModuleDict({
139
+ s["name"]: nn.Linear(_H, s["out_dim"]) for s in specs})
140
+
141
+ def forward(self, name, x):
142
+ return self.heads[name](self.trunk(self.adapters[name](x)))
143
+
144
+ return MultiTask()
145
+
146
+
147
+ def _train(net, specs, steps=_STEPS, seed=uq.SEED):
148
+ t = torch(); nn = t.nn
149
+ opt = t.optim.Adam(net.parameters(), lr=3e-3)
150
+ mse = nn.MSELoss(); bce = nn.BCEWithLogitsLoss()
151
+ rng = np.random.default_rng(seed)
152
+ # pre-tensor the standardized train sets
153
+ packs = []
154
+ for sp in specs:
155
+ Xn = t.tensor(_stdx(sp, sp["Xtr"]))
156
+ Yn = t.tensor(_stdy(sp, sp["Ytr"]))
157
+ packs.append((sp, Xn, Yn))
158
+ net.train()
159
+ for _ in range(steps):
160
+ opt.zero_grad(); loss = 0.0
161
+ for sp, Xn, Yn in packs:
162
+ m = len(Xn); b = min(_BATCH, m)
163
+ idx = t.tensor(rng.choice(m, b, replace=False))
164
+ out = net(sp["name"], Xn[idx])
165
+ loss = loss + (bce(out, Yn[idx]) if sp["kind"] == "cls"
166
+ else mse(out, Yn[idx]))
167
+ loss.backward(); opt.step()
168
+ net.eval()
169
+ return net
170
+
171
+
172
+ def _mc_forward(net, name, Xn, kind, passes=_MC):
173
+ """MC-dropout: keep dropout ON, run several passes -> (mean, std)."""
174
+ t = torch()
175
+ net.train() # dropout active
176
+ outs = []
177
+ with t.no_grad():
178
+ for _ in range(passes):
179
+ o = net(name, t.tensor(np.asarray(Xn, "float32"))).numpy()
180
+ outs.append(_sigmoid(o) if kind == "cls" else o)
181
+ net.eval()
182
+ outs = np.array(outs)
183
+ return outs.mean(0), outs.std(0)
184
+
185
+
186
+ def _sigmoid(z):
187
+ return 1.0 / (1.0 + np.exp(-np.clip(z, -30, 30)))
188
+
189
+
190
+ def _domain_metric(sp, pred_std_mean):
191
+ """Score the (standardized) prediction against the held-out truth in the
192
+ domain's OWN metric. pred_std_mean is the standardized-space mean output."""
193
+ kind = sp["kind"]; Yte = sp["Yte"]
194
+ if kind == "cls":
195
+ from sklearn.metrics import roc_auc_score
196
+ p = _sigmoid(pred_std_mean).ravel()
197
+ auc = float(roc_auc_score(Yte.ravel(), p)) if len(np.unique(Yte)) > 1 else float("nan")
198
+ return {"metric": "roc_auc", "value": round(auc, 3), "higher_better": True}
199
+ pred = _invy(sp, pred_std_mean)
200
+ if sp["name"] == "transport":
201
+ return {"metric": "r2_log_Qtot", "value": round(metrics.r2(Yte.ravel(), pred.ravel()), 3),
202
+ "higher_better": True}
203
+ if sp["name"] == "equil":
204
+ rl2 = float(np.mean([metrics.rel_l2(Yte[i], pred[i]) for i in range(len(Yte))]))
205
+ return {"metric": "rel_l2_field", "value": round(rl2, 4), "higher_better": False}
206
+ # state: range-normalized RMSE (KFLOW convention)
207
+ rng = sp["Ytr"].max(0) - sp["Ytr"].min(0) + 1e-9
208
+ nrmse = float(np.sqrt(np.mean(((pred - Yte) / rng) ** 2)))
209
+ return {"metric": "norm_rmse", "value": round(nrmse, 4), "higher_better": False}
210
+
211
+
212
+ @register
213
+ class KMIND(Surrogate):
214
+ name = "KMIND"; function = "FOUNDATION"; phase = 3; status = "BUILT"
215
+ provenance = "SIM"
216
+ retired_by = "a device-scale multi-task foundation model on real multi-diagnostic data"
217
+ real_codes = ("multi-task representation learning", "KYRO", "KORE", "KFLOW", "KWARD")
218
+ gates = ("BR-L2-A1e", "AC-16", "AC-18", "AC-20")
219
+ note = ("whole-device foundation surrogate — one shared-trunk multi-task net across "
220
+ "transport / equilibrium / state / disruption, trained jointly; reports "
221
+ "shared-representation transfer honestly (incl. negative transfer)")
222
+
223
+ def __init__(self):
224
+ self._net = None; self._specs = None
225
+
226
+ def _fit(self):
227
+ if self._net is None:
228
+ self._specs = [_spec(n) for n in _DOMAINS]
229
+ self._net = _train(_build_net(self._specs), self._specs)
230
+ return self._net, self._specs
231
+
232
+ def _sp(self, name):
233
+ _, specs = self._fit()
234
+ for sp in specs:
235
+ if sp["name"] == name:
236
+ return sp
237
+ raise KeyError(name)
238
+
239
+ def _predict(self, x):
240
+ """x = (domain, input) or {"domain": name, "x": input}, domain in
241
+ {transport, equil, state, disrupt}. -> Prediction(y, MC-dropout std, in_domain)."""
242
+ if isinstance(x, dict):
243
+ name, xi = x.get("domain"), x.get("x")
244
+ elif isinstance(x, (tuple, list)) and len(x) == 2 and x[0] in _DOMAINS:
245
+ name, xi = x
246
+ else:
247
+ raise ValueError("KMIND expects (domain, input) or {'domain','x'}; "
248
+ f"domain in {list(_DOMAINS)}")
249
+ net, _ = self._fit(); sp = self._sp(name)
250
+ Xn = _stdx(sp, xi)
251
+ mean, std = _mc_forward(net, name, Xn, sp["kind"])
252
+ if sp["kind"] == "cls":
253
+ y = float(mean.ravel()[0]); unc = float(std.ravel()[0])
254
+ note = f"{name} head: disruption probability {y:.3f} (MC-dropout std {unc:.3f})"
255
+ else:
256
+ inv_mean = _invy(sp, mean)[0]; inv_std = (std * sp["ysd"])[0]
257
+ y = float(inv_mean) if sp["out_dim"] == 1 else inv_mean
258
+ unc = float(np.mean(inv_std)) if sp["out_dim"] > 1 else float(inv_std)
259
+ tgt = "log10 Q_tot" if name == "transport" else ("psi field" if name == "equil"
260
+ else "clean sensor state")
261
+ note = f"{name} head via shared trunk -> {tgt} (MC-dropout epistemic std)"
262
+ return Prediction(y, unc, _in_domain(sp, xi), note=note)
263
+
264
+ def benchmark(self):
265
+ net, specs = self._fit()
266
+ # multi-task test predictions per domain (deterministic mean, dropout off)
267
+ t = torch()
268
+ multi = {}
269
+ with t.no_grad():
270
+ for sp in specs:
271
+ out = net(sp["name"], t.tensor(_stdx(sp, sp["Xte"]))).numpy()
272
+ multi[sp["name"]] = _domain_metric(sp, out)
273
+ # matched single-task baselines: same architecture (adapter+trunk+head),
274
+ # SAME split + steps, trained on that ONE domain only
275
+ _MIN_TEST = 10 # below this, held-out metric is too noisy to judge
276
+ transfer = {}
277
+ for sp in specs:
278
+ base_net = _train(_build_net([sp]), [sp])
279
+ with t.no_grad():
280
+ bo = base_net(sp["name"], t.tensor(_stdx(sp, sp["Xte"]))).numpy()
281
+ base_m = _domain_metric(sp, bo)
282
+ mm = multi[sp["name"]]
283
+ n_test = int(len(sp["Xte"]))
284
+ delta = round(mm["value"] - base_m["value"], 4)
285
+ if n_test < _MIN_TEST:
286
+ direction = "data_starved" # e.g. transport: 16 pts total, held-out R2 unreliable
287
+ else:
288
+ better = ((mm["value"] > base_m["value"]) if mm["higher_better"]
289
+ else (mm["value"] < base_m["value"]))
290
+ eps = 0.01 if mm["higher_better"] else 0.002
291
+ direction = ("positive" if (better and abs(delta) > eps)
292
+ else "negative" if (not better and abs(delta) > eps) else "neutral")
293
+ transfer[sp["name"]] = {
294
+ "metric": mm["metric"], "multitask": mm["value"],
295
+ "single_task_baseline": base_m["value"], "delta": delta,
296
+ "transfer": direction, "n_train": int(sp["n"] - n_test), "n_test": n_test}
297
+ pos = [d for d, v in transfer.items() if v["transfer"] == "positive"]
298
+ neg = [d for d, v in transfer.items() if v["transfer"] == "negative"]
299
+ neu = [d for d, v in transfer.items() if v["transfer"] == "neutral"]
300
+ starved = [d for d, v in transfer.items() if v["transfer"] == "data_starved"]
301
+ t0 = time.perf_counter()
302
+ for _ in range(50):
303
+ self._predict(("transport", [3.0, 1.0]))
304
+ ms = (time.perf_counter() - t0) / 50 * 1e3
305
+ return {"member": self.name,
306
+ "live_foundation": {
307
+ "architecture": (f"per-domain adapter (->{_D_EMB}) + shared trunk "
308
+ f"(2x{_H}, dropout {_DROP}) + per-domain head; {len(specs)} domains, "
309
+ f"joint training {_STEPS} steps"),
310
+ "domains": list(_DOMAINS),
311
+ "params": int(sum(p.numel() for p in net.parameters())),
312
+ "transfer_vs_single_task": transfer,
313
+ "positive_transfer_domains": pos,
314
+ "negative_transfer_domains": neg,
315
+ "neutral_transfer_domains": neu,
316
+ "data_starved_domains": starved,
317
+ "mc_dropout_predict_ms": round(ms, 2),
318
+ "backend": "CPU, torch, MC-dropout UQ",
319
+ "verdict": (f"One shared trunk across {len(specs)} fusion domains, benchmarked head-by-head "
320
+ f"against a MATCHED single-task baseline on the same split. On the well-populated "
321
+ f"domains the shared representation is positive {pos or 'none'}, negative "
322
+ f"{neg or 'none'}, neutral {neu or 'none'} — "
323
+ f"{'no negative transfer' if not neg else 'some negative transfer'}. "
324
+ + (f"{starved} is data-starved "
325
+ f"({transfer[starved[0]]['n_train'] + transfer[starved[0]]['n_test']} pts) "
326
+ f"and not judged held-out. " if starved else "")
327
+ + f"Trained on real on-disk data (CGYRO map / analytic equilibria / twin "
328
+ f"sensor snapshots / MAST shots) — an honest multi-task result, not a blanket win.")},
329
+ "caveats": ["transport has only ~16 points, so its head is data-starved and high-variance "
330
+ "(a real limit, reported not hidden)",
331
+ "uncertainty is an MC-dropout epistemic proxy, not a calibrated conformal interval",
332
+ "equilibrium targets are the analytic Solov'ev family (as in KORE); state targets "
333
+ "are the analytic-twin sensor snapshots (as in KFLOW)"]}
kronos_ml/members/quantum.py CHANGED
@@ -27,7 +27,7 @@ class KQUBIT(Surrogate):
27
  note = ("REAL variational quantum eigensolver (VQE) for a molecular Hamiltonian — a "
28
  "runnable quantum program (PennyLane): executes on a simulator now and on real "
29
  "quantum hardware when you plug in a backend. Honest: no quantum advantage yet "
30
- "(~8-10 yr out); the tooling + testing are real TODAY")
31
 
32
  # H2 molecular Hamiltonian, 2-qubit parity-reduced (standard Qiskit/IBM textbook coeffs, Ha)
33
  _COEFFS = (-1.052373245772859, 0.39793742484318045, -0.39793742484318045,
@@ -137,7 +137,7 @@ class KQROSS(Surrogate):
137
  note = ("REAL fault-tolerant resource estimator — computes the classical<->quantum crossover N, "
138
  "the surface-code physical-qubit overhead, and the logical-qubit roadmap year for a fusion "
139
  "electronic-structure kernel (order-of-magnitude, literature-scaled). Verdict: no FT "
140
- "advantage this decade — the machine does not exist yet")
141
 
142
  # order-of-magnitude scaling model (literature-scaled; illustrative, honestly labelled)
143
  _D = 25 # surface-code distance
@@ -207,7 +207,7 @@ class KSENSE(Surrogate):
207
  note = ("REAL quantum-metrology evaluation (PennyLane mixed-state) — GHZ interferometry: ideal "
208
  "gives Heisenberg (gain ~ N) scaling, but realistic dephasing (NV/SQUID/SERF reality) "
209
  "collapses it back to the standard quantum limit (~sqrt(N)). Honest null where fusion "
210
- "disruptions live")
211
 
212
  _P = 0.2 # per-qubit dephasing (realistic sensor decoherence)
213
 
@@ -284,7 +284,7 @@ class KTENSOR(Surrogate):
284
  gates = ("KX-L3",)
285
  note = ("tensor-network / low-rank ROM compression of the real CGYRO A1e flux "
286
  "database (classical MPS-style SVD; a many-body method and bridge to "
287
- "quantum kernels — NO quantum-advantage claim)")
288
 
289
  _COLS = ("a_LT", "shear", "Q_i", "Q_e") # operating grid + saturated fluxes
290
 
@@ -395,7 +395,7 @@ class KQERN(Surrogate):
395
  note = ("REAL quantum-kernel classifier — embeds real MAST disruption features into a "
396
  "quantum feature map and classifies on the fidelity kernel (PennyLane); runs on a "
397
  "simulator now, real hardware pluggable. Honest: ties the classical kernel — a "
398
- "validated no-advantage result, but a real, runnable quantum-ML pipeline")
399
 
400
  _N = 64
401
  _FEATS = (0, 6, 7, 8) # ip_mean, beta_n, li, q95 (subset of KWARD's real features)
@@ -490,7 +490,7 @@ class KQOPT(Surrogate):
490
  note = ("REAL QAOA quantum optimizer — solves a combinatorial design QUBO on an actual "
491
  "quantum circuit (PennyLane); runs on a simulator now, real hardware pluggable, and "
492
  "you can plug in your own QUBO. Honest: standard ~0.7-1.0 approx ratio, no speedup "
493
- "at this size (~8-10 yr to advantage)")
494
 
495
  # a fixed 6-node design QUBO (illustrative MaxCut-style configuration problem)
496
  _EDGES = ((0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (0, 2), (3, 5))
@@ -586,7 +586,8 @@ class KDYN(Surrogate):
586
  gates = ("KX-L3",)
587
  note = ("REAL quantum dynamics — Trotterized time-evolution of a transverse-field Ising "
588
  "'kinetic' Hamiltonian (PennyLane); the honest 1/n_steps cost curve for simulating "
589
- "plasma-like dynamics on a quantum computer. Runs on a simulator now, hardware pluggable")
 
590
 
591
  _NQ = 3; _J = 1.0; _HX = 0.8; _T = 1.0
592
 
 
27
  note = ("REAL variational quantum eigensolver (VQE) for a molecular Hamiltonian — a "
28
  "runnable quantum program (PennyLane): executes on a simulator now and on real "
29
  "quantum hardware when you plug in a backend. Honest: no quantum advantage yet "
30
+ "(~8-10 yr out); the tooling + testing are real TODAY — quantum's role in fusion is post-~2036")
31
 
32
  # H2 molecular Hamiltonian, 2-qubit parity-reduced (standard Qiskit/IBM textbook coeffs, Ha)
33
  _COEFFS = (-1.052373245772859, 0.39793742484318045, -0.39793742484318045,
 
137
  note = ("REAL fault-tolerant resource estimator — computes the classical<->quantum crossover N, "
138
  "the surface-code physical-qubit overhead, and the logical-qubit roadmap year for a fusion "
139
  "electronic-structure kernel (order-of-magnitude, literature-scaled). Verdict: no FT "
140
+ "advantage this decade — the machine does not exist yet; meaningful role post-~2036")
141
 
142
  # order-of-magnitude scaling model (literature-scaled; illustrative, honestly labelled)
143
  _D = 25 # surface-code distance
 
207
  note = ("REAL quantum-metrology evaluation (PennyLane mixed-state) — GHZ interferometry: ideal "
208
  "gives Heisenberg (gain ~ N) scaling, but realistic dephasing (NV/SQUID/SERF reality) "
209
  "collapses it back to the standard quantum limit (~sqrt(N)). Honest null where fusion "
210
+ "disruptions live; quantum's role in fusion is post-~2036")
211
 
212
  _P = 0.2 # per-qubit dephasing (realistic sensor decoherence)
213
 
 
284
  gates = ("KX-L3",)
285
  note = ("tensor-network / low-rank ROM compression of the real CGYRO A1e flux "
286
  "database (classical MPS-style SVD; a many-body method and bridge to "
287
+ "quantum kernels — NO quantum-advantage claim; quantum's role in fusion is post-~2036)")
288
 
289
  _COLS = ("a_LT", "shear", "Q_i", "Q_e") # operating grid + saturated fluxes
290
 
 
395
  note = ("REAL quantum-kernel classifier — embeds real MAST disruption features into a "
396
  "quantum feature map and classifies on the fidelity kernel (PennyLane); runs on a "
397
  "simulator now, real hardware pluggable. Honest: ties the classical kernel — a "
398
+ "validated no-advantage result, but a real, runnable quantum-ML pipeline; role in fusion post-~2036")
399
 
400
  _N = 64
401
  _FEATS = (0, 6, 7, 8) # ip_mean, beta_n, li, q95 (subset of KWARD's real features)
 
490
  note = ("REAL QAOA quantum optimizer — solves a combinatorial design QUBO on an actual "
491
  "quantum circuit (PennyLane); runs on a simulator now, real hardware pluggable, and "
492
  "you can plug in your own QUBO. Honest: standard ~0.7-1.0 approx ratio, no speedup "
493
+ "at this size (advantage post-~2036)")
494
 
495
  # a fixed 6-node design QUBO (illustrative MaxCut-style configuration problem)
496
  _EDGES = ((0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (0, 2), (3, 5))
 
586
  gates = ("KX-L3",)
587
  note = ("REAL quantum dynamics — Trotterized time-evolution of a transverse-field Ising "
588
  "'kinetic' Hamiltonian (PennyLane); the honest 1/n_steps cost curve for simulating "
589
+ "plasma-like dynamics on a quantum computer. Runs on a simulator now, hardware pluggable; "
590
+ "quantum's role in fusion is post-~2036")
591
 
592
  _NQ = 3; _J = 1.0; _HX = 0.8; _T = 1.0
593
 
kronos_ml/members/quantum_v3.py ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """KODEX v0.3.0 quantum additions — honest, runnable-today NISQ tooling.
2
+
3
+ KMIT — quantum ERROR MITIGATION: zero-noise extrapolation (ZNE) + readout-error
4
+ mitigation applied to a real fusion quantum circuit (the KQUBIT H2 VQE
5
+ state). Mitigation is the technique NISQ practitioners actually run
6
+ today — it claws signal back out of noise; it is NOT a speedup.
7
+ KLINQ — quantum LINEAR SOLVER: a variational quantum linear solver (VQLS) that
8
+ prepares the solution of a small reduced-MHD linear system with a real
9
+ quantum circuit, plus an honest fault-tolerant HHL resource estimate.
10
+
11
+ Framing (founder, 2026-09-19): we see quantum computing taking a meaningful role
12
+ in fusion only AFTER ~2036 — the tooling and testing are real and runnable TODAY
13
+ (here, on a simulator now and on real hardware via KODEX_QC_BACKEND=ibm), the
14
+ advantage is not.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import numpy as np
19
+
20
+ from .. import register, get
21
+ from ..base import Surrogate, Prediction
22
+ from .. import quantum_backend as qc
23
+
24
+ _QC_ROLE_YEAR = 2036 # honest: quantum's meaningful role in fusion is post-~2036
25
+
26
+
27
+ # ============================================================ KMIT
28
+ @register
29
+ class KMIT(Surrogate):
30
+ name = "KMIT"; function = "QMITIGATION"; phase = 2; status = "BUILT"
31
+ provenance = "SIM"
32
+ retired_by = "fault-tolerant quantum hardware (not available this decade)"
33
+ real_codes = ("zero-noise extrapolation", "readout-error mitigation", "PennyLane")
34
+ gates = ("KX-L3",)
35
+ note = ("REAL quantum error mitigation — zero-noise extrapolation (ZNE, unitary "
36
+ "folding) + readout-error mitigation on a real fusion quantum circuit "
37
+ "(the KQUBIT H2 VQE state). Mitigation is the genuine NISQ tool TODAY; it "
38
+ f"recovers signal from noise, not a speedup. Quantum's role in fusion is "
39
+ f"post-~{_QC_ROLE_YEAR}")
40
+
41
+ _P = 0.04 # per-qubit depolarizing rate (NISQ-ish)
42
+ _READOUT = 0.08 # per-qubit readout bit-flip probability
43
+
44
+ # ---- ZNE on the KQUBIT H2 VQE circuit ----
45
+ def _zne(self):
46
+ import pennylane as qml
47
+ kq = get("KQUBIT"); kq._run_vqe()
48
+ params, H = kq._vqe_params, kq._hamiltonian()
49
+ ansatz = kq._ansatz
50
+ exact = kq._vqe["exact_energy_Ha"]
51
+
52
+ dev_clean = qml.device("default.qubit", wires=2)
53
+
54
+ @qml.qnode(dev_clean)
55
+ def ideal():
56
+ ansatz(params)
57
+ return qml.expval(H)
58
+ e_ideal = float(ideal()) # noiseless expval at the VQE params
59
+
60
+ dev = qml.device("default.mixed", wires=2)
61
+
62
+ def _noise():
63
+ for w in (0, 1):
64
+ qml.DepolarizingChannel(self._P, wires=w)
65
+
66
+ @qml.qnode(dev)
67
+ def folded(k):
68
+ """Global unitary folding: ansatz (adjoint.ansatz)^k -> logical ansatz,
69
+ noise scale lambda = 2k+1."""
70
+ ansatz(params); _noise()
71
+ for _ in range(k):
72
+ qml.adjoint(ansatz)(params); _noise()
73
+ ansatz(params); _noise()
74
+ return qml.expval(H)
75
+
76
+ lambdas = np.array([1, 3, 5], float) # k = 0, 1, 2
77
+ energies = np.array([float(folded(int((lam - 1) / 2))) for lam in lambdas])
78
+ # linear ZNE extrapolation to zero noise
79
+ slope, intercept = np.polyfit(lambdas, energies, 1)
80
+ e_noisy = float(energies[0])
81
+ e_zne = float(intercept)
82
+ err_noisy = abs(e_noisy - e_ideal)
83
+ err_zne = abs(e_zne - e_ideal)
84
+ reduction = (err_noisy - err_zne) / err_noisy if err_noisy > 1e-9 else 0.0
85
+ return {"exact_energy_Ha": round(exact, 6),
86
+ "ideal_noiseless_Ha": round(e_ideal, 6),
87
+ "noisy_Ha": round(e_noisy, 6),
88
+ "zne_mitigated_Ha": round(e_zne, 6),
89
+ "noise_scales_lambda": lambdas.tolist(),
90
+ "energies_vs_lambda": [round(float(e), 6) for e in energies],
91
+ "error_noisy_mHa": round(err_noisy * 1e3, 3),
92
+ "error_zne_mHa": round(err_zne * 1e3, 3),
93
+ "error_reduction_frac": round(float(reduction), 3),
94
+ "depolarizing_p": self._P, "backend": qc.backend_note()}
95
+
96
+ # ---- readout-error mitigation on a Bell distribution ----
97
+ def _readout_mitigation(self):
98
+ r = self._READOUT
99
+ ideal = np.array([0.5, 0.0, 0.0, 0.5]) # Bell |Phi+> probs
100
+ M1 = np.array([[1 - r, r], [r, 1 - r]]) # per-qubit readout confusion
101
+ M = np.kron(M1, M1)
102
+ noisy = M @ ideal
103
+ mitig = np.linalg.solve(M, noisy)
104
+ mitig = np.clip(mitig, 0, None); mitig = mitig / mitig.sum()
105
+ tv = lambda a, b: float(0.5 * np.abs(a - b).sum())
106
+ tv_noisy, tv_mit = tv(noisy, ideal), tv(mitig, ideal)
107
+ return {"readout_bitflip_p": r,
108
+ "tv_distance_noisy": round(tv_noisy, 4),
109
+ "tv_distance_mitigated": round(tv_mit, 4),
110
+ "tv_reduction_frac": round((tv_noisy - tv_mit) / tv_noisy, 3) if tv_noisy > 1e-9 else 0.0,
111
+ "method": "inverse confusion-matrix (linear) readout correction"}
112
+
113
+ def _predict(self, x):
114
+ """x = per-qubit depolarizing rate p (float) -> ZNE-mitigated H2 energy at that noise."""
115
+ if x is not None:
116
+ try:
117
+ self._P = float(np.ravel(np.asarray(x, float))[0])
118
+ except Exception:
119
+ pass
120
+ z = self._zne()
121
+ return Prediction(z["zne_mitigated_Ha"], z["error_zne_mHa"], True,
122
+ note=(f"ZNE-mitigated H2 energy {z['zne_mitigated_Ha']} Ha "
123
+ f"(noisy err {z['error_noisy_mHa']} -> {z['error_zne_mHa']} mHa); "
124
+ f"backend={z['backend']['active_backend']}"))
125
+
126
+ def benchmark(self):
127
+ z = self._zne(); ro = self._readout_mitigation()
128
+ return {"member": self.name,
129
+ "live_error_mitigation": {
130
+ "problem": "mitigate a noisy H2 VQE expectation (the real KQUBIT circuit)",
131
+ "framework": "PennyLane default.mixed; ZNE via global unitary folding + linear extrapolation",
132
+ "zne": z, "readout_mitigation": ro,
133
+ "backend": z["backend"],
134
+ "verdict": (f"REAL error mitigation on a fusion quantum circuit: ZNE cuts the noisy-energy "
135
+ f"error {z['error_noisy_mHa']} -> {z['error_zne_mHa']} mHa "
136
+ f"({z['error_reduction_frac']:.0%} of the error removed) and inverse-confusion "
137
+ f"readout correction cuts the measurement TV distance "
138
+ f"{ro['tv_distance_noisy']} -> {ro['tv_distance_mitigated']} "
139
+ f"({ro['tv_reduction_frac']:.0%}). Mitigation is the REAL NISQ tool today — it "
140
+ f"recovers signal from noise. HONEST: it is NOT a speedup; quantum's meaningful "
141
+ f"role in fusion is post-~{_QC_ROLE_YEAR}, and mitigation cost grows with noise. "
142
+ f"Runs on real hardware with KODEX_QC_BACKEND=ibm.")},
143
+ "caveats": [f"no quantum advantage — quantum's role in fusion is post-~{_QC_ROLE_YEAR}",
144
+ "ZNE assumes a smooth noise->observable relation; it extrapolates, it does not "
145
+ "eliminate noise, and its overhead grows as noise grows",
146
+ "readout mitigation uses a known confusion matrix; on hardware you must calibrate it"]}
147
+
148
+
149
+ # ============================================================ KLINQ
150
+ @register
151
+ class KLINQ(Surrogate):
152
+ name = "KLINQ"; function = "QLINSOLVE"; phase = 3; status = "BUILT"
153
+ provenance = "SIM"
154
+ retired_by = "fault-tolerant quantum hardware (not available this decade)"
155
+ real_codes = ("variational quantum linear solver", "HHL resource estimate", "PennyLane")
156
+ gates = ("KX-L3",)
157
+ note = ("REAL quantum linear solver — a variational quantum linear solver (VQLS) prepares the "
158
+ "solution of a small reduced-MHD linear system with a real quantum circuit (sim now, "
159
+ "hardware pluggable), plus an honest fault-tolerant HHL resource estimate. No advantage "
160
+ f"at real scale; quantum's role in fusion is post-~{_QC_ROLE_YEAR}")
161
+
162
+ _NQ = 2 # N = 4 linear system
163
+ _N = 4
164
+
165
+ def _system(self, b=None):
166
+ """A small SPD reduced-MHD operator: 1-D discrete Laplacian (tridiagonal),
167
+ the shape a linearized force-balance / diffusion solve takes."""
168
+ A = (np.diag([2.0] * self._N) + np.diag([-1.0] * (self._N - 1), 1)
169
+ + np.diag([-1.0] * (self._N - 1), -1))
170
+ if b is None:
171
+ b = np.array([1.0, 0.0, 0.0, 0.0])
172
+ b = np.asarray(b, float).ravel()[: self._N]
173
+ b = b / (np.linalg.norm(b) + 1e-12)
174
+ return A, b
175
+
176
+ def _ansatz_state(self, theta, dev):
177
+ import pennylane as qml
178
+
179
+ @qml.qnode(dev)
180
+ def state(t):
181
+ # 2-layer hardware-efficient ansatz on 2 qubits
182
+ qml.RY(t[0], 0); qml.RY(t[1], 1)
183
+ qml.CNOT([0, 1])
184
+ qml.RY(t[2], 0); qml.RY(t[3], 1)
185
+ qml.CNOT([1, 0])
186
+ qml.RY(t[4], 0); qml.RY(t[5], 1)
187
+ return qml.state()
188
+ return np.real(np.asarray(state(theta))) # SPD system -> real solution
189
+
190
+ def _solve(self, b=None):
191
+ if getattr(self, "_res", None) is not None and b is None:
192
+ return self._res
193
+ import pennylane as qml
194
+ from scipy.optimize import minimize
195
+ from .. import uq
196
+ A, bvec = self._system(b)
197
+ dev = qc.get_device(wires=self._NQ)
198
+
199
+ def cost(theta):
200
+ x = self._ansatz_state(theta, dev)
201
+ Ax = A @ x
202
+ nAx = np.linalg.norm(Ax) + 1e-12
203
+ overlap = float(bvec @ (Ax / nAx)) # want A|x> parallel to |b>
204
+ return 1.0 - overlap ** 2 # global VQLS cost
205
+
206
+ rng = np.random.default_rng(uq.SEED)
207
+ best = None
208
+ for _ in range(4): # a few restarts for robustness
209
+ t0 = rng.uniform(0, 2 * np.pi, 6)
210
+ r = minimize(cost, t0, method="Powell",
211
+ options={"maxiter": 4000, "xtol": 1e-8, "ftol": 1e-10})
212
+ if best is None or r.fun < best.fun:
213
+ best = r
214
+ theta = best.x
215
+ x_q = self._ansatz_state(theta, dev)
216
+ # VQLS solves up to scale & sign: fix by projecting onto the classical solution direction
217
+ x_cl = np.linalg.solve(A, bvec)
218
+ x_q_dir = x_q / (np.linalg.norm(x_q) + 1e-12)
219
+ x_cl_dir = x_cl / (np.linalg.norm(x_cl) + 1e-12)
220
+ if x_q_dir @ x_cl_dir < 0:
221
+ x_q_dir = -x_q_dir
222
+ fidelity = float((x_q_dir @ x_cl_dir) ** 2) # state fidelity of the solutions
223
+ # rescale quantum direction to the true magnitude for a usable x
224
+ alpha = float((A @ x_q_dir) @ bvec) / float((A @ x_q_dir) @ (A @ x_q_dir) + 1e-12)
225
+ x_q_scaled = alpha * x_q_dir
226
+ resid = float(np.linalg.norm(A @ x_q_scaled - bvec) / (np.linalg.norm(bvec) + 1e-12))
227
+ res = {"N": self._N, "n_qubits": self._NQ, "cost_final": round(float(best.fun), 6),
228
+ "solution_fidelity_vs_classical": round(fidelity, 4),
229
+ "residual_rel": round(resid, 4),
230
+ "x_quantum": [round(float(v), 4) for v in x_q_scaled],
231
+ "x_classical": [round(float(v), 4) for v in x_cl],
232
+ "backend": qc.backend_note()}
233
+ if b is None:
234
+ self._res = res
235
+ return res
236
+
237
+ # ---- honest fault-tolerant HHL resource estimate (KQROSS-style) ----
238
+ def _hhl_estimate(self, N=1_000_000, kappa=1e3, precision_bits=10):
239
+ """Order-of-magnitude FT-HHL cost for a fusion-scale sparse linear solve."""
240
+ n_logical = int(np.ceil(np.log2(N))) + precision_bits + 1 # system + clock + ancilla
241
+ phys_per_logical = 2 * 25 * 25 # surface code d=25 (~1250)
242
+ phys = n_logical * phys_per_logical
243
+ # HHL ~ O(kappa/eps) calls; classical CG ~ O(sqrt(kappa)) matvecs — quantum needs
244
+ # sparse, well-conditioned, and only reads out an aggregate, else state-prep/readout kill it
245
+ roadmap_year = 2027 + 3.0 * np.log10(max(n_logical, 1) / 1.0) # ~10x logical / 3 yr from ~1 in 2027
246
+ return {"assumed_system": f"N~{N:.0e} sparse SPD (reduced-MHD grid), kappa~{kappa:.0e}",
247
+ "logical_qubits_needed": n_logical,
248
+ "physical_qubits_needed": f"~{phys:.0e}",
249
+ "surface_code_phys_per_logical": phys_per_logical,
250
+ "roadmap_year_reach_logical": int(round(roadmap_year)),
251
+ "hardware_today": "~1e2-1e3 physical qubits, no error-corrected logical qubits",
252
+ "caveats": ["HHL needs fault tolerance + sparse, well-conditioned A + efficient state "
253
+ "prep, and returns |x> (aggregate readout), not the full vector",
254
+ f"no fusion HHL advantage this decade — meaningful role post-~{_QC_ROLE_YEAR}"]}
255
+
256
+ def _predict(self, x):
257
+ """x = right-hand-side vector b (len<=4) or None -> quantum solution x of A x = b."""
258
+ r = self._solve(None if x is None else x)
259
+ return Prediction(r["x_quantum"], r["residual_rel"], True,
260
+ note=(f"VQLS solution (fidelity {r['solution_fidelity_vs_classical']} vs classical, "
261
+ f"rel-residual {r['residual_rel']}); backend={r['backend']['active_backend']}"))
262
+
263
+ def benchmark(self):
264
+ r = self._solve()
265
+ hhl = self._hhl_estimate()
266
+ return {"member": self.name,
267
+ "live_quantum_linear_solver": {
268
+ "problem": "solve A x = b for a 4x4 reduced-MHD Laplacian (SPD) with a real quantum circuit",
269
+ "method": "variational quantum linear solver (VQLS), global overlap cost, Powell optimization",
270
+ "framework": "PennyLane (sim now; Hadamard-test cost on real hardware, pluggable)",
271
+ **{k: r[k] for k in ("N", "n_qubits", "cost_final", "solution_fidelity_vs_classical",
272
+ "residual_rel", "x_quantum", "x_classical")},
273
+ "ft_hhl_resource_estimate": hhl, "backend": r["backend"],
274
+ "verdict": (f"REAL variational quantum linear solver recovers the 4x4 reduced-MHD solve at "
275
+ f"solution fidelity {r['solution_fidelity_vs_classical']} vs classical "
276
+ f"(rel-residual {r['residual_rel']}) — a runnable quantum linear solver TODAY. "
277
+ f"The fault-tolerant HHL route for a fusion-scale (N~1e6) solve needs "
278
+ f"~{hhl['logical_qubits_needed']} logical -> {hhl['physical_qubits_needed']} "
279
+ f"physical qubits (roadmap ~{hhl['roadmap_year_reach_logical']}). HONEST: no "
280
+ f"advantage at real scale; quantum's meaningful role in fusion is "
281
+ f"post-~{_QC_ROLE_YEAR}. Runs on hardware with KODEX_QC_BACKEND=ibm.")},
282
+ "caveats": [f"no quantum advantage — quantum's role in fusion is post-~{_QC_ROLE_YEAR}",
283
+ "VQLS residual is read from the simulator here; on hardware it needs Hadamard "
284
+ "tests and its cost landscape can have barren plateaus at scale",
285
+ "the 4x4 system is a toy; classical solves it instantly — the point is a real, "
286
+ "honest, hardware-ready quantum pipeline, not a speedup"]}
kronos_ml/quantum_backend.py CHANGED
@@ -62,6 +62,7 @@ def backend_note() -> dict:
62
  "ran_on_real_hardware": real,
63
  "how_to_use_real_qc": ("set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum "
64
  "token> to run this exact circuit on real quantum hardware"),
65
- "honest_timeline": ("fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out; "
66
- "this tooling makes the TESTING real and runnable TODAY, same code path"),
 
67
  }
 
62
  "ran_on_real_hardware": real,
63
  "how_to_use_real_qc": ("set KODEX_QC_BACKEND=ibm and KODEX_QC_TOKEN=<your IBM Quantum "
64
  "token> to run this exact circuit on real quantum hardware"),
65
+ "honest_timeline": ("fault-tolerant quantum ADVANTAGE for fusion kernels is ~8-10 yr out — a "
66
+ "meaningful role in fusion only after ~2036; this tooling makes the TESTING "
67
+ "real and runnable TODAY, same code path"),
68
  }
publish/LIVE_RECORDS.md DELETED
@@ -1,36 +0,0 @@
1
- # KODEX — live deposit records (per code)
2
-
3
- Status 2026-09-10: **Zenodo, OSF, Figshare = published** (26 each). **Harvard Dataverse = 25 submitted for curator review** (DOIs reserved; publish on Harvard approval) — **KLAW (doi:10.7910/DVN/ANAFXK) still to submit**. GitHub / PyPI / Hugging Face / Internet Archive = pending.
4
-
5
- Author: Ford, P. I. · ORCID 0000-0003-0395-1752 · Kronos Fusion Energy · Apache-2.0. Each record's homepage = kronosfusionenergy.com/kodex/<code>.
6
-
7
- | Code | Zenodo DOI | Figshare DOI | Dataverse DOI (in review) | OSF |
8
- |--|--|--|--|--|
9
- | **KAIROS** | 10.5281/zenodo.22694265 | 10.6084/m9.figshare.33553966 | 10.7910/DVN/GOZGCM | [db6uh](https://osf.io/db6uh/) |
10
- | **KBREED** | 10.5281/zenodo.22694267 | 10.6084/m9.figshare.33559312 | 10.7910/DVN/OPJHP3 | [2m3ce](https://osf.io/2m3ce/) |
11
- | **KBURN** | 10.5281/zenodo.22694269 | 10.6084/m9.figshare.33559324 | 10.7910/DVN/ITN6JZ | [8e6fn](https://osf.io/8e6fn/) |
12
- | **KDRIVE** | 10.5281/zenodo.22694271 | 10.6084/m9.figshare.33559333 | 10.7910/DVN/YKKLQ7 | [xhkuy](https://osf.io/xhkuy/) |
13
- | **KECON** | 10.5281/zenodo.22694273 | 10.6084/m9.figshare.33559345 | 10.7910/DVN/WBHQ7S | [b5qmx](https://osf.io/b5qmx/) |
14
- | **KEYE** | 10.5281/zenodo.22694279 | 10.6084/m9.figshare.33559357 | 10.7910/DVN/5UILC8 | [5qzp4](https://osf.io/5qzp4/) |
15
- | **KFLOW** | 10.5281/zenodo.22694283 | 10.6084/m9.figshare.33559369 | 10.7910/DVN/XUXC7B | [hjrzb](https://osf.io/hjrzb/) |
16
- | **KFLUX** | 10.5281/zenodo.22694287 | 10.6084/m9.figshare.33559378 | 10.7910/DVN/3F0NCW | [fmjc2](https://osf.io/fmjc2/) |
17
- | **KFORGE** | 10.5281/zenodo.22694289 | 10.6084/m9.figshare.33559390 | 10.7910/DVN/OVOVVN | [5zg6j](https://osf.io/5zg6j/) |
18
- | **KFUEL** | 10.5281/zenodo.22694291 | 10.6084/m9.figshare.33559402 | 10.7910/DVN/89A8GS | [xuz8a](https://osf.io/xuz8a/) |
19
- | **KFUSE** | 10.5281/zenodo.22694294 | 10.6084/m9.figshare.33559414 | 10.7910/DVN/SMA2OP | [exhkc](https://osf.io/exhkc/) |
20
- | **KGATE** | 10.5281/zenodo.22694297 | 10.6084/m9.figshare.33559423 | 10.7910/DVN/2CKPZH | [mbu37](https://osf.io/mbu37/) |
21
- | **KGEN** | 10.5281/zenodo.22694307 | 10.6084/m9.figshare.33559435 | 10.7910/DVN/OCTF8U | [svbwq](https://osf.io/svbwq/) |
22
- | **KHALO** | 10.5281/zenodo.22694309 | 10.6084/m9.figshare.33559447 | 10.7910/DVN/V5YM23 | [ne89y](https://osf.io/ne89y/) |
23
- | **KISO** | 10.5281/zenodo.22694311 | 10.6084/m9.figshare.33559459 | 10.7910/DVN/ELXAEY | [hjqek](https://osf.io/hjqek/) |
24
- | **KLAW** | 10.5281/zenodo.22694315 | 10.6084/m9.figshare.33559468 | 10.7910/DVN/ANAFXK | [kfp4t](https://osf.io/kfp4t/) |
25
- | **KMAT** | 10.5281/zenodo.22694319 | 10.6084/m9.figshare.33559480 | 10.7910/DVN/IJG9FT | [y4j2p](https://osf.io/y4j2p/) |
26
- | **KOIL** | 10.5281/zenodo.22694323 | 10.6084/m9.figshare.33559492 | 10.7910/DVN/N5WLNR | [2rb68](https://osf.io/2rb68/) |
27
- | **KORE** | 10.5281/zenodo.22694327 | 10.6084/m9.figshare.33559504 | 10.7910/DVN/DCFLOI | [sxm5v](https://osf.io/sxm5v/) |
28
- | **KPATH** | 10.5281/zenodo.22694329 | 10.6084/m9.figshare.33559513 | 10.7910/DVN/8QIUD4 | [fbcyw](https://osf.io/fbcyw/) |
29
- | **KPILOT** | 10.5281/zenodo.22694331 | 10.6084/m9.figshare.33559525 | 10.7910/DVN/EYD6FZ | [aqxe8](https://osf.io/aqxe8/) |
30
- | **KQROSS** | 10.5281/zenodo.22694333 | 10.6084/m9.figshare.33559537 | 10.7910/DVN/IIDBCF | [zp82a](https://osf.io/zp82a/) |
31
- | **KQUBIT** | 10.5281/zenodo.22694336 | 10.6084/m9.figshare.33559546 | 10.7910/DVN/2BC8BL | [eqr9z](https://osf.io/eqr9z/) |
32
- | **KSENSE** | 10.5281/zenodo.22694338 | 10.6084/m9.figshare.33559558 | 10.7910/DVN/5LQJAF | [psr8h](https://osf.io/psr8h/) |
33
- | **KWARD** | 10.5281/zenodo.22694342 | 10.6084/m9.figshare.33559570 | 10.7910/DVN/VPYXHS | [ugfpr](https://osf.io/ugfpr/) |
34
- | **KYRO** | 10.5281/zenodo.22694348 | 10.6084/m9.figshare.33559582 | 10.7910/DVN/2YQQOX | [5m6vu](https://osf.io/5m6vu/) |
35
-
36
- _Generated from publish/state/*.json. Zenodo/Figshare DOIs are permanent; Dataverse DOIs activate when Harvard curators approve the review submissions._
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/MANIFEST.sha256 DELETED
@@ -1,41 +0,0 @@
1
- # KODEX SHA-256 manifest (v0.1.0, 2026-09-10)
2
-
3
- 2ac66d4d7d4a89054d47e15215b9d6eca8e527503763b9b05c85b65160f5d8ec .gitignore
4
- 8695a176b58590a0bbc6b7ede1c0ce4a270c54115aa06777e1462bfebe86bd1a .zenodo.json
5
- b1ee5fa8a901a64265186e58788f420b94c37151a61144a3c24ed37d782325e3 BENCHMARKS.md
6
- 9bb42b66491b72e95cfc26b4139c767ec7eda643d479061183c65af55db56d44 CITATION.cff
7
- 889dc088a39f3b908cc627dcbd09e252a75abea42f716f664eafcf7d8b7ff578 CODES.md
8
- 16f411de9a68f30ea8f05572c7a2aebe8cd923acec35bb55441b1a92861ce7c2 FAMILY.md
9
- ae87ebecd1f321a19799e21f6fe25e4a74261f16c91e6cb6cc248e6197dcf838 LICENSE
10
- faf6dbd85a3cd3b9879201b7470e7ba858ae560108b7c984ec33809081d51a3d README.md
11
- 8d2e3d7856756d03007be14187b5dd5bf10e22160e9f04103015141c04643d42 benchmarks/benchmarks.json
12
- 361ef1108dc3ea2c4d6499b47ea4617a528a53bef4254abafdb889568a2772d3 benchmarks/run_all.py
13
- 5e138e573eeaaaf7a5c2b0c74570adbf7cb132058f2c8c2dd7c25e3c18a4d77f checkpoints/kore_mlp_seed0.pt
14
- a251c80fc84f2c46be0a8aa822bc5a3619c32019627d0d35001531d0b5d3be19 checkpoints/kore_mlp_seed1.pt
15
- 525cecaf99600dd7ccddb1d25a84fa216ab71739d73c39b62bb04d1e434bfd76 checkpoints/kore_mlp_seed2.pt
16
- 6e5136d13e3e0b8335d146e65dce940b54e38e0e6a7bfe1fbdb3af8ea8483d88 codemeta.json
17
- 162d8a2ba10cead49dd9be7276dc7c57177f151f174d1ea623ad1f65fce2d43a demo.ipynb
18
- b4233195b725817a61d1801f7c744159486076bae1c3bb9fd7d0e9ab9070f3dd kronos_ml/__init__.py
19
- 835650847427eb59f9240a6bbcd1db4ec739eacef974aa0200944bbe3348043e kronos_ml/_torch.py
20
- c094cca7d3393317f8e412f41211b073be1701560b8c2923f84ab1e0bf770753 kronos_ml/base.py
21
- 510bf0fe2c2ce159dec25629ad903e3b0de1e97fdc2621b80efce87e4d6c33a7 kronos_ml/data.py
22
- 5d34c8aec99f9f7c5e6f62cb3b02b1aafeb311bb94d38f880d9ae6de63e51733 kronos_ml/members/__init__.py
23
- e5b88836b177c757a4f2db0925eac364ad12abe8c18038e14be9432286c03e61 kronos_ml/members/advanced.py
24
- f87aaf941a7ee00200f18bd35d68880e5365d62aa48bb029ab64e0091f16888e kronos_ml/members/capstone.py
25
- 2b1d273280c16b1771cf1fd745aa558b967d9dac0684eb722dfdc867812fe9d1 kronos_ml/members/control.py
26
- 5c340f9813497f5382b3a5324b76311b216f5696c9d8f3b2d0fb8f7491d7f671 kronos_ml/members/disrupt.py
27
- 3f881fef3d4b8b255907c3adda0c3936b335c4aadb51e7a566bf4095bd058c29 kronos_ml/members/equil.py
28
- 56d7f4b0b4072224772e3a59f1642ef4e5f5afaf70575636775a73a891f6e0d3 kronos_ml/members/fusion.py
29
- a8639ff450bb27a42771a2251ee852291ecaf09c4a1795cfc790ce67a84b808e kronos_ml/members/magnet.py
30
- 9265df980412b82ef2185fb3d143c93780f4da76fda72fa4b6b010b6ae06b3de kronos_ml/members/materials.py
31
- f843996eeaa949e470ecce22713e5505649ce9fc1a7f5a6cdfca425a2ded09dc kronos_ml/members/neutronics.py
32
- 2708133806780dce88184fa19c03b3760f207788c78d9e8edddcecd35f991e5e kronos_ml/members/plant.py
33
- ad05706b4f588e413b1314ebe7b3069c57a21ccf040d6fb762eb731aeda41584 kronos_ml/members/quantum.py
34
- c9b921c1131b95831366c0197663b486ea1c9a302b119ef3880249d6c897c7bf kronos_ml/members/roadmap.py
35
- 75c01157cea0ab64f6a3458d76e69fa2be386fd5e4c6168d6e08d41e46a53c15 kronos_ml/members/spine.py
36
- eca2a363d02653b4fbe5e68df2ca41ecb5c277fd66fea22694681d648ecf7f64 kronos_ml/members/state.py
37
- f6466e59e49482d4423fb0415e3a7e4377eada9d2544a734a23a82974730e60f kronos_ml/members/transport.py
38
- 508a45df51b194c435bfdd2d79658bff66bb77913a0ea66cea40116a7867266a kronos_ml/metrics.py
39
- 578e86ef6f3faa7cce6682541d6cedb52c7f652d187085088dc3a4e8ccd4b5db kronos_ml/uq.py
40
- 0f1af657ccf7539ab9dbbc2dd5408afa08085670d9c896bd5e95cbb4352124ec pyproject.toml
41
- 54516950a748b00bc0992388ae3ae1a3fda3739307e7f2b651670896fb30c823 tests/test_contract.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/PROVENANCE.md DELETED
@@ -1,42 +0,0 @@
1
- # KODEX provenance & traceability (v0.1.0, 2026-09-10)
2
-
3
- Each BUILT code traces: **code -> real benchmark -> on-disk data/method -> Kronos corpus DOI -> /kodex page.**
4
-
5
- | # | Code | Ph | Provenance | Real source/method | Corpus anchor | Page |
6
- |--|--|--|--|--|--|--|
7
- | 01 | **KAIROS** | 1 | TWIN | receding-horizon MPC | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kairos |
8
- | 02 | **KBREED** | 2 | SIM | openmc | references:10.5281/zenodo.22645689 | kbreed |
9
- | 03 | **KBURN** | 2 | TWIN | plant systems model | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kburn |
10
- | 04 | **KDRIVE** | 3 | TWIN | reinforcement learning | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kdrive |
11
- | 05 | **KECON** | 3 | n/a | open LCOE methodology | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kecon |
12
- | 06 | **KEYE** | 2 | SIM | sensor fusion, signal validation | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | keye |
13
- | 07 | **KFLOW** | 1 | SIM | message-passing GNN | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kflow |
14
- | 08 | **KFLUX** | 2 | SIM | openmc | references:10.5281/zenodo.22645689 | kflux |
15
- | 09 | **KFORGE** | 3 | CGYRO-urep | differential evolution over the fleet | isDerivedFrom:10.5281/zenodo.22136279 | kforge |
16
- | 10 | **KFUEL** | 3 | SIM | fuel-cycle systems model | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kfuel |
17
- | 11 | **KFUSE** | 2 | CGYRO-urep | multi-fidelity GP, CGYRO | isDerivedFrom:10.5281/zenodo.22136279 | kfuse |
18
- | 12 | **KGATE** | 1 | TWIN | CBF certificate, hardware failsafe | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kgate |
19
- | 13 | **KGEN** | 3 | ANALYTIC | generative model | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kgen |
20
- | 14 | **KHALO** | 1 | SIM | deep-ensemble, conformal | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | khalo |
21
- | 15 | **KISO** | 2 | SIM | isotope PI servo, FENDL-3.2 activation | references:10.5281/zenodo.22645689; isDerivedFrom:https://www-nds.iaea.org/fendl/ | kiso |
22
- | 16 | **KLAW** | 3 | CGYRO-urep | sparse regression / SINDy | isDerivedFrom:10.5281/zenodo.22136279 | klaw |
23
- | 17 | **KMAT** | 1 | SIM | CHGNet, DFT | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kmat |
24
- | 18 | **KOIL** | 1 | SIM | finite-element stress solve | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | koil |
25
- | 19 | **KORE** | 1 | ANALYTIC | Grad-Shafranov FD solver | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kore |
26
- | 20 | **KPATH** | 2 | TWIN | MPC scenario optimizer | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kpath |
27
- | 21 | **KPILOT** | 3 | n/a | fleet router / tool dispatcher | references:10.5281/zenodo.21842371; references:10.5281/zenodo.22645689 | kpilot |
28
- | 22 | **KQROSS** | 2 | SIM | FT resource estimation | isDerivedFrom:10.5281/zenodo.21842371 | kqross |
29
- | 23 | **KQUBIT** | 1 | SIM | VQE, quantum chemistry | isDerivedFrom:10.5281/zenodo.21842371 | kqubit |
30
- | 24 | **KSENSE** | 2 | SIM | NV/SQUID/SERF magnetometry | isDerivedFrom:10.5281/zenodo.21842371 | ksense |
31
- | 25 | **KWARD** | 1 | REAL-ANCHOR | real MAST shots (FAIR-MAST) | isDerivedFrom:https://mastapp.site; references:10.5281/zenodo.22645689 | kward |
32
- | 26 | **KYRO** | 1 | CGYRO-urep | cgyro, gene, gs2, tglf | isDerivedFrom:10.5281/zenodo.22136279 | kyro |
33
-
34
- ## Held as ROADMAP (4)
35
-
36
- - **KEDGE** (ROADMAP, phase 3) — divertor / SOL / edge heat-flux transport surrogate
37
- - **KHEAT** (PARTIAL, phase 2) — RF / NBI heating & current-drive actuator-response surrogate
38
- - **KRAD** (ROADMAP, phase 3) — impurity seeding / radiation / divertor-detachment control
39
- - **KTENSOR** (PARTIAL, phase 2) — tensor-network simulation & compression — a classical many-body method and a bridge to quantum for kernel problems
40
-
41
- Anchor DOIs: CGYRO `10.5281/zenodo.22136279` · Register `10.5281/zenodo.22645689` · AI+Quantum `10.5281/zenodo.21842371` · toolkit https://github.com/KronosFE/kronos-toolkit
42
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/PUBLISH_RUNBOOK.md DELETED
@@ -1,158 +0,0 @@
1
- # KODEX — publish runbook (PER-CODE, DRAFT-FIRST)
2
-
3
- **Release:** KODEX v0.1.0 — the Kronos Family of Codes.
4
- **Model:** **26 per-code records** on each data repository (Zenodo / OSF / Figshare / Harvard Dataverse /
5
- Internet Archive) — each BUILT code gets its own record + DOI. **GitHub = ONE repo** (`kronos-ml`, 26
6
- modules). **PyPI = ONE package** (`kronos-ml`, 26 importable codes). **Held as ROADMAP (not published):**
7
- KHEAT, KTENSOR, KEDGE, KRAD.
8
- **Author on every record:** Ford, P. I. · ORCID `0000-0003-0395-1752` · Kronos Fusion Energy · Apache-2.0.
9
-
10
- > **Draft-first, two-step per data venue.** Step 1 `*_draft.py` creates all 26 records as **private/
11
- > unpublished** and uploads each code's files — nothing is public. Step 2 `*_publish_all.py` is a **dry run
12
- > by default** and publishes only with an explicit **`--yes`** — that `--yes` is your single deliberate
13
- > authorization for that venue's 26. The draft scripts NEVER publish; the publish scripts do nothing
14
- > without `--yes`. (Internet Archive is one step — items are public on upload — so `ia_upload_all.py`
15
- > requires `--yes` and IS the publish.)
16
-
17
- Per-code metadata lives in `publish/records/<code>/metadata.json`; each record's homepage is
18
- `kronosfusionenergy.com/kodex/<code>`, with its physics-source + the shared Kronos anchors
19
- (register `10.5281/zenodo.22645689`, CGYRO `10.5281/zenodo.22136279`, AI+Quantum `10.5281/zenodo.21842371`,
20
- toolkit) as related-identifiers, honest card preserved. Per-code attach set: `<code>.py` (source excerpt),
21
- `benchmark.json`, `card.md`, `CITATION.cff`, `LICENSE`, `MANIFEST.sha256`. The repo-root `.zenodo.json`,
22
- `CITATION.cff`, `codemeta.json` describe the **GitHub/PyPI package** (the one-repo/one-package side).
23
-
24
- ## Token map
25
-
26
- | Venue | Credential | Env var | Status |
27
- |---|---|---|---|
28
- | GitHub | SSH key | — | ✅ ready |
29
- | Zenodo | token `deposit:write` | `ZENODO_TOKEN` | ✅ ready |
30
- | OSF | token `osf.full_write` | `OSF_TOKEN` | ✅ ready |
31
- | Figshare | personal token | `FIGSHARE_TOKEN` | ✅ ready |
32
- | Internet Archive | `ia configure` (S3 keys) | — | ✅ ready |
33
- | Harvard Dataverse | API token (115-paper/books token) | `DATAVERSE_TOKEN` + `DATAVERSE_CONTACT_EMAIL` | ⏳ token needed |
34
- | PyPI | API token | `TWINE_PASSWORD` (`TWINE_USERNAME=__token__`) | ⏳ fast-follow |
35
- | Hugging Face | write token | `HF_TOKEN` | ⏳ fast-follow |
36
-
37
- ## Preflight (once)
38
-
39
- ```bash
40
- cd "/Users/pford/Desktop/Kronos Fusion Energy/04 - IT INFRASTRUCTURE/07 - IT Infrastructure & Code Repos/Code Repos (live)/kronos-ml"
41
- PY=~/kronos-hpc-build/ml311_venv/bin/python
42
- $PY -m pytest tests/ -q # expect 9 passed
43
- $PY publish/_percode.py # (re)builds publish/records/<code>/ for all 26 (resume-safe)
44
- ```
45
-
46
- > ⚠ **numpy pin:** this venv must keep **numpy<2** (torch 2.2.2 needs it; numpy 2.x breaks KORE). If a
47
- > tool ever pulls numpy 2.x back in, run `$PY -m pip install "numpy==1.26.4"` before benchmarking.
48
-
49
- ---
50
-
51
- ## 1) GitHub — ONE repo (git@github.com:KronosFE/kronos-ml.git)
52
-
53
- ```bash
54
- git init -b main
55
- git add .
56
- git commit -m "KODEX v0.1.0 — Kronos Family of Codes (26 BUILT surrogates)"
57
- git tag -a v0.1.0 -m "KODEX v0.1.0"
58
- # create the repo PRIVATE on GitHub, then:
59
- git remote add origin git@github.com:KronosFE/kronos-ml.git
60
- git push -u origin main --tags
61
- # → review; when ready, make public + draft a Release from tag v0.1.0.
62
- # Do NOT enable the GitHub↔Zenodo webhook (we deposit Zenodo per-code below).
63
- ```
64
-
65
- ## 2) Zenodo — 26 per-code records
66
-
67
- ```bash
68
- export ZENODO_TOKEN=... # rehearse first: export ZENODO_BASE=https://sandbox.zenodo.org
69
- $PY publish/zenodo_draft.py # creates 26 DRAFTS (resume-safe), nothing public
70
- $PY publish/zenodo_publish_all.py # DRY RUN — lists the 26 drafts
71
- $PY publish/zenodo_publish_all.py --yes # ← your one authorization: publishes all 26, mints DOIs
72
- ```
73
-
74
- ## 3) OSF — 26 private projects → public
75
-
76
- ```bash
77
- export OSF_TOKEN=...
78
- $PY publish/osf_draft.py # 26 PRIVATE projects
79
- $PY publish/osf_publish_all.py # DRY RUN
80
- $PY publish/osf_publish_all.py --yes # ← make all 26 public
81
- ```
82
-
83
- ## 4) Figshare — 26 draft articles → published
84
-
85
- ```bash
86
- export FIGSHARE_TOKEN=...
87
- $PY publish/figshare_draft.py # 26 DRAFT articles (DOIs reserved, not published)
88
- $PY publish/figshare_publish_all.py # DRY RUN
89
- $PY publish/figshare_publish_all.py --yes
90
- ```
91
-
92
- ## 5) Harvard Dataverse — 26 datasets (published by CURATORS, not by --yes)
93
-
94
- STATUS 2026-09-10: the 26 drafts are created; **25 were submitted for Harvard curator review**
95
- (`review:true` in state) and publish when a Harvard **curator approves** — NOT via a depositor
96
- `--yes`. `dataverse_publish_all.py` now refuses to `:publish` review-queued datasets (a direct
97
- publish on an In-Review dataset errors), so `--yes` is a no-op for the 25. Two open items before
98
- curators approve (the published version is immutable):
99
-
100
- 1. **KLAW** (`doi:10.7910/DVN/ANAFXK`) was NOT submitted for review — submit it so it isn't stranded:
101
- ```bash
102
- export DATAVERSE_TOKEN=...
103
- curl -H "X-Dataverse-key:$DATAVERSE_TOKEN" -X POST \
104
- "https://dataverse.harvard.edu/api/datasets/:persistentId/submitForReview?persistentId=doi:10.7910/DVN/ANAFXK"
105
- # then set "review": true for KLAW in publish/state/dataverse_drafts.json
106
- ```
107
- 2. **License field**: the drafts carry no dataset-level license, so Harvard will publish them as
108
- **CC0** unless Apache-2.0 is set. Check + set before approval:
109
- ```bash
110
- curl -s -H "X-Dataverse-key:$DATAVERSE_TOKEN" https://dataverse.harvard.edu/api/licenses | grep -i apache
111
- # if Apache-2.0 is installed, set it on each draft version (API) before curator approval;
112
- # otherwise the Apache-2.0 statement in the description + bundled LICENSE stand, and you accept CC0.
113
- ```
114
- (Re-running `dataverse_draft.py` is safe — it skips the 26 already-created datasets.)
115
-
116
- ## 6) Internet Archive — 26 items (public on upload; one step)
117
-
118
- ```bash
119
- ia configure # once, with your IA S3 keys
120
- $PY publish/ia_upload_all.py # DRY RUN — lists the 26 item identifiers
121
- $PY publish/ia_upload_all.py --yes # ← uploads 26 items (PUBLIC immediately)
122
- ```
123
-
124
- ---
125
-
126
- ## Fast-follow (when the tokens land)
127
-
128
- ### PyPI — ONE package
129
- ```bash
130
- $PY -m build
131
- export TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-...
132
- $PY -m twine upload --repository testpypi dist/* # rehearse first
133
- $PY -m twine upload dist/*
134
- ```
135
-
136
- ### Hugging Face — per-code model repos (or one)
137
- ```bash
138
- export HF_TOKEN=...
139
- $PY -m pip install -q huggingface_hub
140
- # one suite repo:
141
- huggingface-cli upload KronosFE/kronos-ml . . --repo-type=model --token "$HF_TOKEN"
142
- # (per-code repos KronosFE/kodex-<code> can be scripted the same way if preferred)
143
- ```
144
-
145
- ---
146
-
147
- ## Rollback (discard drafts — nothing was public)
148
- - **Zenodo / Figshare / Dataverse:** delete the unpublished drafts in each UI (or via each API).
149
- - **OSF:** projects are private until `--yes`; delete in the UI.
150
- - **GitHub:** repo stays private until you flip it.
151
- - **Internet Archive:** items are public on upload — only run `--yes` when you're sure; ask IA support to
152
- dark an item if needed.
153
- - Re-running any `*_draft.py` is safe: it skips codes already in `publish/state/<venue>_drafts.json`.
154
-
155
- ## Provenance recorded in every record
156
- code → real benchmark (`benchmark.json`) → on-disk data/method → Kronos corpus DOI → `/kodex/<code>` page.
157
- Honest cards intact: μ=400 representative-mass (CGYRO codes); validated null result (quantum codes);
158
- KWARD heuristic labels + independent-precursor AUC 0.975 (n=1 Mirnov + P_rad only); KECON financial firewall.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/_deposit_common.py DELETED
@@ -1,68 +0,0 @@
1
- """Shared helpers for the KODEX draft-first deposits.
2
-
3
- Builds a clean release archive and defines the attach list + metadata. Imported by
4
- zenodo_draft.py / osf_draft.py / figshare_draft.py. NONE of those scripts ever call
5
- a venue's publish/complete endpoint — they create a DRAFT and upload files, then
6
- print the draft URL for the founder to review and publish herself.
7
- """
8
- from __future__ import annotations
9
- import json, os, zipfile
10
- from pathlib import Path
11
-
12
- REPO = Path(__file__).resolve().parent.parent
13
- PUB = REPO / "publish"
14
- VERSION = json.load(open(PUB / "_scaffolding_summary.json"))["version"]
15
- ARCHIVE = PUB / f"kronos-ml-v{VERSION}-source.zip"
16
-
17
- # individual human-readable artifacts attached alongside the source archive
18
- DOCS = ["README.md", "FAMILY.md", "CODES.md", "BENCHMARKS.md", "benchmarks/benchmarks.json",
19
- "demo.ipynb", "CITATION.cff", "LICENSE", "codemeta.json", ".zenodo.json",
20
- "publish/PROVENANCE.md", "publish/MANIFEST.sha256"]
21
-
22
- _SKIP_DIRS = {"__pycache__", ".git", ".ipynb_checkpoints", ".pytest_cache", "dist"}
23
- _SKIP_SUFFIX = {".pyc", ".pyo"}
24
-
25
-
26
- def build_archive() -> Path:
27
- """Zip the whole package (source + tests + docs + manifest), minus cruft."""
28
- with zipfile.ZipFile(ARCHIVE, "w", zipfile.ZIP_DEFLATED) as z:
29
- for root, dirs, files in os.walk(REPO):
30
- dirs[:] = [d for d in dirs if d not in _SKIP_DIRS]
31
- for fn in files:
32
- p = Path(root) / fn
33
- if p.suffix in _SKIP_SUFFIX or p == ARCHIVE:
34
- continue
35
- if p.name.endswith(".parquet"):
36
- continue
37
- z.write(p, p.relative_to(REPO))
38
- return ARCHIVE
39
-
40
-
41
- def attach_paths() -> list[Path]:
42
- """Full attach set: the source archive + the individual docs f7 asked for."""
43
- out = [build_archive()]
44
- for rel in DOCS:
45
- p = REPO / rel
46
- if p.exists():
47
- out.append(p)
48
- return out
49
-
50
-
51
- def zenodo_metadata() -> dict:
52
- return json.load(open(REPO / ".zenodo.json"))
53
-
54
-
55
- def require_env(var: str) -> str:
56
- v = os.environ.get(var)
57
- if not v:
58
- raise SystemExit(f"[STOP] environment variable {var} is not set. "
59
- f"Export your token first (see PUBLISH_RUNBOOK.md).")
60
- return v
61
-
62
-
63
- if __name__ == "__main__":
64
- paths = attach_paths()
65
- print(f"archive: {ARCHIVE.name}")
66
- print(f"attach set ({len(paths)} files):")
67
- for p in paths:
68
- print(f" {p.relative_to(REPO)} ({p.stat().st_size:,} B)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/_percode.py DELETED
@@ -1,256 +0,0 @@
1
- """Per-code deposit engine for KODEX (26 BUILT codes -> 26 records per data venue).
2
-
3
- Generates publish/records/<kname>/ (metadata + per-code attach set) and provides the
4
- shared helpers the venue scripts use to loop. State (created draft ids/DOIs) is written
5
- to publish/state/<venue>_drafts.json so a run can resume and the batch-publish step
6
- knows exactly what to act on.
7
-
8
- DRAFT-FIRST: nothing here publishes. The *_draft.py scripts create drafts; the separate
9
- *_publish_all.py scripts publish only drafts listed in the state file, only with --yes.
10
- """
11
- from __future__ import annotations
12
- import hashlib, html, inspect, json, os, random, re, shutil, sys, time
13
- from datetime import date
14
- from pathlib import Path
15
-
16
- _RETRY_CODES = {403, 408, 425, 429, 500, 502, 503, 504}
17
-
18
-
19
- def http_retry(fn, *, tries=6, base=0.8, label=""):
20
- """Call fn() -> requests.Response; retry transient/rate-limit codes with expo backoff.
21
- Returns the final Response (caller still checks .ok / raises). 2xx returns immediately."""
22
- r = None
23
- for i in range(tries):
24
- r = fn()
25
- if 200 <= r.status_code < 300 or r.status_code not in _RETRY_CODES or i == tries - 1:
26
- return r
27
- wait = base * (2 ** i) + random.random() * 0.4
28
- sys.stderr.write(f" [retry] {label} {r.status_code}; sleep {wait:.1f}s ({i+1}/{tries})\n")
29
- time.sleep(wait)
30
- return r
31
-
32
- REPO = Path(__file__).resolve().parent.parent
33
- PUB = REPO / "publish"
34
- REC_ROOT = PUB / "records"
35
- STATE_ROOT = PUB / "state"
36
- sys.path.insert(0, str(REPO)); sys.path.insert(0, str(REPO.parent / "kronos-toolkit"))
37
- os.environ.setdefault("PYTHONWARNINGS", "ignore")
38
- import warnings; warnings.filterwarnings("ignore")
39
- import kronos_ml as K
40
-
41
- TODAY = date.today().isoformat()
42
- VERSION = K.__version__
43
- ORCID = "0000-0003-0395-1752"
44
- AFFIL = "Kronos Fusion Energy"
45
- KODEX = "https://kronosfusionenergy.com/kodex"
46
- REPO_URL = "https://github.com/KronosFE/kronos-ml"
47
- TOOLKIT_URL = "https://github.com/KronosFE/kronos-toolkit"
48
- LICENSE = "Apache-2.0"
49
-
50
- DOI_REGISTER = "10.5281/zenodo.22645689"
51
- DOI_CGYRO = "10.5281/zenodo.22136279"
52
- DOI_AIQ = "10.5281/zenodo.21842371"
53
-
54
- KEYWORDS_BASE = ["fusion energy", "spherical tokamak", "D-3He", "AI/ML surrogate model",
55
- "uncertainty quantification", "digital twin", "Kronos Fusion Energy"]
56
-
57
-
58
- def built():
59
- """The codes a publish run acts on: every BUILT code, unless KODEX_PUBLISH_ONLY
60
- restricts it to an explicit allow-list (comma/space-separated code names).
61
-
62
- The allow-list is how an operator deposits a deliberate SUBSET (e.g. only the
63
- v0.2.0 additions) without touching the rest of the fleet — it does NOT change any
64
- code's real status, so the package stays honest. Unset = all BUILT (default). A
65
- named code that is not currently BUILT is a hard error, so a typo can never
66
- silently narrow (or widen) the set.
67
- """
68
- names = sorted(n for n in K.list_surrogates() if K.get(n).status == "BUILT")
69
- only = os.environ.get("KODEX_PUBLISH_ONLY", "").strip()
70
- if only:
71
- want = {c.strip().upper() for c in re.split(r"[,\s]+", only) if c.strip()}
72
- unknown = want - set(names)
73
- if unknown:
74
- raise SystemExit(f"[STOP] KODEX_PUBLISH_ONLY names not in the BUILT set: "
75
- f"{sorted(unknown)} (BUILT: {names})")
76
- names = [n for n in names if n in want]
77
- sys.stderr.write(f"[scope] KODEX_PUBLISH_ONLY -> {len(names)} codes: {names}\n")
78
- return names
79
-
80
-
81
- def physics_source(s):
82
- """(relation, identifier, note) list tracing a code to its real physics source."""
83
- p = (s.provenance or "").upper()
84
- if "CGYRO" in p:
85
- return [("isDerivedFrom", DOI_CGYRO, "CGYRO A1e nonlinear-kinetic turbulence map (mu=400)")]
86
- if p == "REAL-ANCHOR":
87
- return [("isDerivedFrom", "https://mastapp.site", "FAIR-MAST real-device data (UKAEA)")]
88
- if s.name in ("KQUBIT", "KQROSS", "KSENSE", "KTENSOR"):
89
- return [("isDerivedFrom", DOI_AIQ, "Kronos AI + Quantum deposit")]
90
- if s.name in ("KBREED", "KFLUX"):
91
- return [("references", DOI_REGISTER, "De-Risking Register neutronics gates")]
92
- if s.name == "KISO":
93
- return [("isDerivedFrom", "https://www-nds.iaea.org/fendl/", "FENDL-3.2 activation data (IAEA)"),
94
- ("references", DOI_REGISTER, "De-Risking Register")]
95
- return [("references", DOI_AIQ, "Kronos AI + Quantum corpus")]
96
-
97
-
98
- def _headline(name, b):
99
- try:
100
- from benchmarks.run_all import _headline as hl
101
- return hl(name, b)
102
- except Exception:
103
- return (b or {}).get("note", "")
104
-
105
-
106
- def record_meta(name, b=None):
107
- s = K.get(name); kn = name.lower()
108
- if b is None:
109
- b = s.benchmark()
110
- page = f"{KODEX}/{kn}"
111
- src = physics_source(s)
112
- related = [{"relation": "isDocumentedBy", "identifier": page, "resource_type": "publication-other"},
113
- {"relation": "isPartOf", "identifier": KODEX, "resource_type": "publication-other"},
114
- {"relation": "isSupplementTo", "identifier": REPO_URL, "resource_type": "software"},
115
- {"relation": "references", "identifier": DOI_REGISTER, "resource_type": "publication"},
116
- {"relation": "isCompiledBy", "identifier": TOOLKIT_URL, "resource_type": "software"}]
117
- for rel, ident, _ in src:
118
- rtype = "dataset" if ident.startswith("10.") or "mast" in ident or "fendl" in ident else "other"
119
- related.append({"relation": rel, "identifier": ident, "resource_type": rtype})
120
- # dedupe by (relation, identifier), keeping first (e.g. register DOI appended by both
121
- # the base list and physics_source for KBREED/KFLUX/KISO)
122
- _seen, _ded = set(), []
123
- for r in related:
124
- k = (r["relation"], r["identifier"])
125
- if k not in _seen:
126
- _seen.add(k); _ded.append(r)
127
- related = _ded
128
- desc = (f"<p><strong>KODEX &mdash; {name}</strong> ({s.function}). {(s.note or '').strip()}</p>"
129
- f"<p><strong>Benchmark:</strong> {_headline(name, b)}</p>"
130
- f"<p>Part of KODEX, the Kronos Family of Codes &mdash; a benchmarked AI/ML fusion "
131
- f"surrogate suite with calibrated uncertainty and an abstention gate "
132
- f"(<code>predict(x) &rarr; (y, uncertainty, in_domain)</code>). Provenance: "
133
- f"{'; '.join(f'{r} {i}' for r, i, _ in src)}. Home: <a href=\"{page}\">{page}</a> &middot; "
134
- f"suite: <a href=\"{REPO_URL}\">{REPO_URL}</a>. Licensed under Apache-2.0. "
135
- f"Honest card preserved verbatim.</p>")
136
- # plaintext variant for venues whose description field does NOT render HTML (OSF)
137
- desc_plain = html.unescape(re.sub(r"<[^>]+>", "", desc)).strip()
138
- return {
139
- "kname": name, "page": page,
140
- "title": f"KODEX — {name}: {s.function}",
141
- "version": VERSION, "publication_date": TODAY, "language": "eng",
142
- "upload_type": "software",
143
- "creators": [{"name": "Ford, P. I.", "orcid": ORCID, "affiliation": AFFIL}],
144
- "license": {"id": LICENSE},
145
- "keywords": KEYWORDS_BASE + [s.function, f"KODEX:{name}"],
146
- "related_identifiers": related,
147
- "description": desc,
148
- "description_plain": desc_plain,
149
- "notes": (f"Draft-first per-code deposit. Full package: {REPO_URL}. "
150
- f"Provenance chain in card.md + MANIFEST.sha256."),
151
- }
152
-
153
-
154
- def _sha(p):
155
- h = hashlib.sha256()
156
- with open(p, "rb") as f:
157
- for c in iter(lambda: f.read(1 << 16), b""):
158
- h.update(c)
159
- return h.hexdigest()
160
-
161
-
162
- def build_records():
163
- REC_ROOT.mkdir(parents=True, exist_ok=True)
164
- STATE_ROOT.mkdir(parents=True, exist_ok=True)
165
- names = built()
166
- for name in names:
167
- d = REC_ROOT / name.lower()
168
- if (d / "metadata.json").exists() and (d / "MANIFEST.sha256").exists():
169
- continue # resume: already generated
170
- s = K.get(name); kn = name.lower()
171
- b = s.benchmark() # compute ONCE, reuse
172
- d.mkdir(exist_ok=True)
173
- # 1) source excerpt (the class), readable
174
- try:
175
- src_code = inspect.getsource(type(s))
176
- except Exception:
177
- src_code = f"# source not extractable for {name}\n"
178
- (d / f"{kn}.py").write_text(
179
- f'"""KODEX {name} — source excerpt (class). Full runnable package: {REPO_URL}"""\n\n'
180
- + src_code)
181
- # 2) benchmark
182
- (d / "benchmark.json").write_text(json.dumps(b, default=str, indent=2) + "\n")
183
- # 3) card
184
- c = s.card()
185
- (d / "card.md").write_text(
186
- f"# KODEX {name} — card\n\n"
187
- + "\n".join(f"- **{k}:** {v}" for k, v in c.items()) + "\n\n"
188
- + f"Benchmark headline: {_headline(name, b)}\n")
189
- # 4) per-code CITATION.cff
190
- (d / "CITATION.cff").write_text("\n".join([
191
- "cff-version: 1.2.0",
192
- f"title: \"KODEX — {name}: {s.function} (Kronos Family of Codes)\"",
193
- f"version: \"{VERSION}\"", f"date-released: \"{TODAY}\"",
194
- f"license: {LICENSE}", f"url: \"{KODEX}/{kn}\"",
195
- f"repository-code: \"{REPO_URL}\"", "type: software", "authors:",
196
- " - family-names: Ford", " given-names: \"P. I.\"",
197
- f" orcid: \"https://orcid.org/{ORCID}\"", f" affiliation: \"{AFFIL}\"",
198
- ]) + "\n")
199
- # 5) LICENSE
200
- shutil.copyfile(REPO / "LICENSE", d / "LICENSE")
201
- # 6) metadata
202
- (d / "metadata.json").write_text(json.dumps(record_meta(name, b), indent=2) + "\n")
203
- # 7) manifest
204
- files = [p for p in sorted(d.iterdir()) if p.name != "MANIFEST.sha256"]
205
- (d / "MANIFEST.sha256").write_text(
206
- f"# KODEX {name} SHA-256 ({VERSION}, {TODAY})\n"
207
- + "\n".join(f"{_sha(p)} {p.name}" for p in files) + "\n")
208
- (PUB / "_percode_summary.json").write_text(json.dumps(
209
- {"version": VERSION, "date": TODAY, "n_records": len(names), "codes": names}, indent=2) + "\n")
210
- return names
211
-
212
-
213
- def record_dir(kname):
214
- return REC_ROOT / kname.lower()
215
-
216
-
217
- def attach_paths(kname):
218
- d = record_dir(kname)
219
- # metadata.json is included so the uploaded file set exactly equals the set the
220
- # MANIFEST.sha256 hashes (sha256sum -c then verifies clean; -c skips the un-self-listed manifest)
221
- order = [f"{kname.lower()}.py", "benchmark.json", "card.md",
222
- "CITATION.cff", "LICENSE", "metadata.json", "MANIFEST.sha256"]
223
- return [d / f for f in order if (d / f).exists()]
224
-
225
-
226
- def load_meta(kname):
227
- return json.loads((record_dir(kname) / "metadata.json").read_text())
228
-
229
-
230
- def state_path(venue):
231
- return STATE_ROOT / f"{venue}_drafts.json"
232
-
233
-
234
- def read_state(venue):
235
- p = state_path(venue)
236
- return json.loads(p.read_text()) if p.exists() else {}
237
-
238
-
239
- def write_state(venue, st):
240
- STATE_ROOT.mkdir(parents=True, exist_ok=True)
241
- state_path(venue).write_text(json.dumps(st, indent=2) + "\n")
242
-
243
-
244
- def require_env(var):
245
- v = os.environ.get(var)
246
- if not v:
247
- raise SystemExit(f"[STOP] environment variable {var} is not set (see PUBLISH_RUNBOOK.md).")
248
- return v
249
-
250
-
251
- if __name__ == "__main__":
252
- names = build_records()
253
- print(f"built {len(names)} per-code records under publish/records/:")
254
- for n in names:
255
- ap = attach_paths(n)
256
- print(f" {n.lower():9s} {len(ap)} files, meta title={load_meta(n)['title']!r}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/_percode_summary.json DELETED
@@ -1,42 +0,0 @@
1
- {
2
- "version": "0.2.0",
3
- "date": "2026-09-11",
4
- "n_records": 35,
5
- "codes": [
6
- "KAIROS",
7
- "KBENCH",
8
- "KBREED",
9
- "KBURN",
10
- "KDRIVE",
11
- "KDYN",
12
- "KECON",
13
- "KEDGE",
14
- "KEYE",
15
- "KFLOW",
16
- "KFLUX",
17
- "KFORGE",
18
- "KFUEL",
19
- "KFUSE",
20
- "KGATE",
21
- "KGEN",
22
- "KHALO",
23
- "KHEAT",
24
- "KISO",
25
- "KLAW",
26
- "KMAT",
27
- "KOIL",
28
- "KORE",
29
- "KPATH",
30
- "KPILOT",
31
- "KQERN",
32
- "KQOPT",
33
- "KQROSS",
34
- "KQUBIT",
35
- "KRAD",
36
- "KSEEK",
37
- "KSENSE",
38
- "KTENSOR",
39
- "KWARD",
40
- "KYRO"
41
- ]
42
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/_scaffolding_summary.json DELETED
@@ -1,40 +0,0 @@
1
- {
2
- "version": "0.1.0",
3
- "date": "2026-09-10",
4
- "built": [
5
- "KAIROS",
6
- "KBREED",
7
- "KBURN",
8
- "KDRIVE",
9
- "KECON",
10
- "KEYE",
11
- "KFLOW",
12
- "KFLUX",
13
- "KFORGE",
14
- "KFUEL",
15
- "KFUSE",
16
- "KGATE",
17
- "KGEN",
18
- "KHALO",
19
- "KISO",
20
- "KLAW",
21
- "KMAT",
22
- "KOIL",
23
- "KORE",
24
- "KPATH",
25
- "KPILOT",
26
- "KQROSS",
27
- "KQUBIT",
28
- "KSENSE",
29
- "KWARD",
30
- "KYRO"
31
- ],
32
- "n_built": 26,
33
- "held": [
34
- "KEDGE",
35
- "KHEAT",
36
- "KRAD",
37
- "KTENSOR"
38
- ],
39
- "n_files_hashed": 39
40
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/dataverse_draft.py DELETED
@@ -1,105 +0,0 @@
1
- #!/usr/bin/env python
2
- """Create 26 DRAFT Harvard Dataverse datasets (one per BUILT KODEX code) in the
3
- kronos-fusion-energy collection.
4
-
5
- DRAFT-FIRST: Dataverse datasets are created UNPUBLISHED. Never calls the publish
6
- action. Resume-safe via publish/state/dataverse_drafts.json (pid recorded the moment
7
- the dataset is created). Prints the API error body on failure so a 400 names its field.
8
- After review, run dataverse_publish_all.py --yes.
9
-
10
- export DATAVERSE_TOKEN=...
11
- export DATAVERSE_CONTACT_EMAIL=... # shown PUBLICLY — use a public-safe address
12
- # optional: DATAVERSE_COLLECTION=kronos-fusion-energy DATAVERSE_BASE=https://dataverse.harvard.edu
13
- python publish/dataverse_draft.py
14
- """
15
- from __future__ import annotations
16
- import os, sys
17
- import requests
18
- from _percode import built, attach_paths, load_meta, read_state, write_state, require_env, ORCID
19
-
20
- BASE = os.environ.get("DATAVERSE_BASE", "https://dataverse.harvard.edu").rstrip("/")
21
- COLLECTION = os.environ.get("DATAVERSE_COLLECTION", "kronos-fusion-energy")
22
-
23
-
24
- def _prim(name, value, multiple=False, cls="primitive"):
25
- return {"typeName": name, "multiple": multiple, "typeClass": cls, "value": value}
26
-
27
-
28
- def _dataset_json(m, contact_email):
29
- author = {"authorName": _prim("authorName", "Ford, P. I."),
30
- "authorAffiliation": _prim("authorAffiliation", "Kronos Fusion Energy"),
31
- "authorIdentifierScheme": {"typeName": "authorIdentifierScheme", "multiple": False,
32
- "typeClass": "controlledVocabulary", "value": "ORCID"},
33
- "authorIdentifier": _prim("authorIdentifier", ORCID)}
34
- contact = {"datasetContactName": _prim("datasetContactName", "Ford, P. I."),
35
- "datasetContactAffiliation": _prim("datasetContactAffiliation", "Kronos Fusion Energy"),
36
- "datasetContactEmail": _prim("datasetContactEmail", contact_email)}
37
- desc = {"dsDescriptionValue": _prim("dsDescriptionValue", m["description"])}
38
- kws = [{"keywordValue": _prim("keywordValue", k)} for k in m["keywords"]]
39
- # only well-formed DOI publications (bare-URL entries live in the description instead)
40
- pubs = []
41
- for r in m["related_identifiers"]:
42
- ident = r["identifier"]
43
- if ident.startswith("10."):
44
- pubs.append({"publicationIDType": {"typeName": "publicationIDType", "multiple": False,
45
- "typeClass": "controlledVocabulary", "value": "doi"},
46
- "publicationIDNumber": _prim("publicationIDNumber", ident),
47
- "publicationURL": _prim("publicationURL", f"https://doi.org/{ident}")})
48
- fields = [_prim("title", m["title"]),
49
- _prim("author", [author], True, "compound"),
50
- _prim("datasetContact", [contact], True, "compound"),
51
- _prim("dsDescription", [desc], True, "compound"),
52
- _prim("subject", ["Physics"], True, "controlledVocabulary"),
53
- _prim("keyword", kws, True, "compound")]
54
- if pubs:
55
- fields.append(_prim("publication", pubs, True, "compound"))
56
- # Harvard's license picker has no Apache-2.0, and a license-less dataset defaults to CC0.
57
- # So set Custom Terms of Use = Apache-2.0 text (per f7's live run) to override the CC0 default.
58
- apache_terms = ("Licensed under the Apache License, Version 2.0 "
59
- "(http://www.apache.org/licenses/LICENSE-2.0). The full license text is in the "
60
- "bundled LICENSE file; citation metadata in CITATION.cff.")
61
- return {"datasetVersion": {"termsOfUse": apache_terms,
62
- "metadataBlocks": {"citation": {"fields": fields}}}}
63
-
64
-
65
- def main():
66
- token = require_env("DATAVERSE_TOKEN")
67
- contact = os.environ.get("DATAVERSE_CONTACT_EMAIL")
68
- if not contact:
69
- raise SystemExit("[STOP] set DATAVERSE_CONTACT_EMAIL (public on the record) first.")
70
- h = {"X-Dataverse-key": token}
71
- s = requests.Session()
72
- state = read_state("dataverse")
73
- names = built()
74
- for i, name in enumerate(names, 1):
75
- rec = state.get(name, {})
76
- if rec.get("done"):
77
- print(f"[dataverse] ({i}/{len(names)}) {name}: complete (skip)"); continue
78
- m = load_meta(name)
79
- pid = rec.get("pid")
80
- if not pid:
81
- r = s.post(f"{BASE}/api/dataverses/{COLLECTION}/datasets", headers=h,
82
- json=_dataset_json(m, contact))
83
- if not r.ok:
84
- print(f"[dataverse] {name}: create FAILED {r.status_code}: {r.text[:500]}")
85
- return 1
86
- pid = r.json()["data"].get("persistentId")
87
- state[name] = {"pid": pid,
88
- "url": f"{BASE}/dataset.xhtml?persistentId={pid}&version=DRAFT"}
89
- write_state("dataverse", state)
90
- for path in attach_paths(name):
91
- with open(path, "rb") as fh:
92
- r = s.post(f"{BASE}/api/datasets/:persistentId/add", headers=h,
93
- params={"persistentId": pid}, files={"file": (path.name, fh)})
94
- if not r.ok and "duplicate" not in r.text.lower() and "exists" not in r.text.lower():
95
- print(f"[dataverse] {name}/{path.name}: add FAILED {r.status_code}: {r.text[:300]}")
96
- return 1
97
- state[name]["done"] = True
98
- write_state("dataverse", state)
99
- print(f"[dataverse] ({i}/{len(names)}) {name}: DRAFT {pid}")
100
- print(f"\n[dataverse] {sum(1 for r in state.values() if r.get('done'))} drafts (NONE published). Then:")
101
- print(" python publish/dataverse_publish_all.py --yes")
102
-
103
-
104
- if __name__ == "__main__":
105
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/dataverse_publish_all.py DELETED
@@ -1,59 +0,0 @@
1
- #!/usr/bin/env python
2
- """Publish the 26 per-code Harvard Dataverse DRAFTS created by dataverse_draft.py.
3
-
4
- IRREVERSIBLE STEP. DRY RUN by default; publishes (major version) only with --yes,
5
- only the datasets recorded in publish/state/dataverse_drafts.json.
6
-
7
- export DATAVERSE_TOKEN=...
8
- python publish/dataverse_publish_all.py # dry run
9
- python publish/dataverse_publish_all.py --yes # publish
10
- """
11
- from __future__ import annotations
12
- import argparse, os, sys
13
- import requests
14
- from _percode import read_state, write_state, require_env
15
-
16
- BASE = os.environ.get("DATAVERSE_BASE", "https://dataverse.harvard.edu").rstrip("/")
17
-
18
-
19
- def main():
20
- ap = argparse.ArgumentParser()
21
- ap.add_argument("--yes", action="store_true")
22
- args = ap.parse_args()
23
- state = read_state("dataverse")
24
- # records submitted for Harvard CURATOR review (review:true) are published by the
25
- # curators on approval, NOT by a depositor :publish call (which errors on an In-Review
26
- # dataset). Only ever direct-publish records that are NOT in the review queue.
27
- in_review = {n: r for n, r in state.items() if r.get("review") and not r.get("published")}
28
- pending = {n: r for n, r in state.items()
29
- if r.get("pid") and not r.get("published") and not r.get("review")}
30
- if in_review:
31
- print(f"[dataverse] {len(in_review)} dataset(s) are in Harvard curator review — "
32
- f"published on curator APPROVAL, not here. Skipping: {', '.join(sorted(in_review))}")
33
- if not pending:
34
- print("[dataverse] no directly-publishable drafts (all are curator-review or already "
35
- "published). Nothing to do — await Harvard curators."); return
36
- print(f"[dataverse] {len(pending)} NON-review draft(s) directly publishable on {BASE}:")
37
- for n, r in pending.items():
38
- print(f" {n:9s} {r['pid']}")
39
- if not args.yes:
40
- print("\n[dataverse] DRY RUN — nothing published. Re-run with --yes.")
41
- return
42
- h = {"X-Dataverse-key": require_env("DATAVERSE_TOKEN")}
43
- s = requests.Session()
44
- ok = 0
45
- for n, r in pending.items():
46
- resp = s.post(f"{BASE}/api/datasets/:persistentId/actions/:publish",
47
- headers=h, params={"persistentId": r["pid"], "type": "major"})
48
- if not resp.ok: # don't let one failure abort the batch
49
- print(f"[dataverse] {n}: publish FAILED {resp.status_code}: {resp.text[:200]}")
50
- continue
51
- r["published"] = True
52
- write_state("dataverse", state)
53
- ok += 1
54
- print(f"[dataverse] PUBLISHED {n}: {r['pid']}")
55
- print(f"\n[dataverse] published {ok}/{len(pending)} non-review records.")
56
-
57
-
58
- if __name__ == "__main__":
59
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/figshare_draft.py DELETED
@@ -1,119 +0,0 @@
1
- #!/usr/bin/env python
2
- """Create 26 DRAFT Figshare articles (one per BUILT KODEX code).
3
-
4
- DRAFT-FIRST: never calls /publish. Creates private articles, reserves DOIs (a
5
- reservation is not a publication), uploads each code's attach set via the multipart
6
- flow. Resume-safe via publish/state/figshare_drafts.json (article id recorded the
7
- moment it is created, so a mid-upload failure never orphans it). After review, run
8
- figshare_publish_all.py --yes.
9
-
10
- export FIGSHARE_TOKEN=...
11
- python publish/figshare_draft.py
12
- """
13
- from __future__ import annotations
14
- import hashlib, sys
15
- import requests
16
- from _percode import built, attach_paths, load_meta, read_state, write_state, require_env
17
-
18
- API = "https://api.figshare.com/v2"
19
-
20
-
21
- def _md5(path):
22
- h = hashlib.md5()
23
- with open(path, "rb") as f:
24
- for c in iter(lambda: f.read(1 << 16), b""):
25
- h.update(c)
26
- return h.hexdigest()
27
-
28
-
29
- def _refs(meta):
30
- """Figshare 'references' must be valid URLs — DOIs -> https://doi.org/..., keep only
31
- http(s), dedupe, preserve order."""
32
- out, seen = [], set()
33
- for r in meta["related_identifiers"]:
34
- ident = r["identifier"].strip()
35
- url = f"https://doi.org/{ident}" if ident.startswith("10.") else ident
36
- if url.startswith("http") and url not in seen:
37
- seen.add(url); out.append(url)
38
- return out
39
-
40
-
41
- def _tags(meta):
42
- """Figshare tags: each >= 3 chars; keep it modest."""
43
- out, seen = [], set()
44
- for k in meta["keywords"]:
45
- k = k.strip()
46
- if len(k) >= 3 and k.lower() not in seen:
47
- seen.add(k.lower()); out.append(k)
48
- return out[:10]
49
-
50
-
51
- def _existing_files(s, h, article_id):
52
- try:
53
- r = s.get(f"{API}/account/articles/{article_id}/files", headers=h)
54
- return {f["name"] for f in r.json()} if r.ok else set()
55
- except Exception:
56
- return set()
57
-
58
-
59
- def _upload(s, h, article_id, path):
60
- size = path.stat().st_size
61
- r = s.post(f"{API}/account/articles/{article_id}/files", headers=h,
62
- json={"name": path.name, "md5": _md5(path), "size": size}); r.raise_for_status()
63
- file_url = r.json()["location"]
64
- info = s.get(file_url, headers=h).json()
65
- up = s.get(info["upload_url"], headers=h).json()
66
- with open(path, "rb") as fh:
67
- for part in up["parts"]:
68
- fh.seek(part["startOffset"])
69
- chunk = fh.read(part["endOffset"] - part["startOffset"] + 1)
70
- s.put(f"{info['upload_url']}/{part['partNo']}", headers=h, data=chunk).raise_for_status()
71
- s.post(file_url, headers=h).raise_for_status()
72
-
73
-
74
- def main():
75
- token = require_env("FIGSHARE_TOKEN")
76
- h = {"Authorization": f"token {token}"}
77
- s = requests.Session()
78
- state = read_state("figshare")
79
- names = built()
80
- for i, name in enumerate(names, 1):
81
- rec = state.get(name, {})
82
- if rec.get("done"):
83
- print(f"[figshare] ({i}/{len(names)}) {name}: complete (skip)"); continue
84
- m = load_meta(name)
85
- aid = rec.get("id")
86
- if not aid:
87
- body = {"title": m["title"], "description": m["description"],
88
- "defined_type": "software", "tags": _tags(m), "references": _refs(m),
89
- # explicit author (ORCID is linked via the uploading Figshare account)
90
- "authors": [{"name": "Ford, P. I."}],
91
- # LEAF categories only — parent 29152 is not assignable (per f7's live run)
92
- "categories": [30202, 29173, 26836]}
93
- r = s.post(f"{API}/account/articles", headers=h, json=body)
94
- if not r.ok:
95
- print(f"[figshare] {name}: create FAILED {r.status_code}: {r.text[:400]}")
96
- print(f" body.tags={body['tags']}")
97
- print(f" body.references={body['references']}")
98
- return 1
99
- aid = int(r.json()["location"].rstrip("/").split("/")[-1])
100
- state[name] = {"id": aid, "url": f"https://figshare.com/account/articles/{aid}"}
101
- write_state("figshare", state)
102
- try:
103
- s.post(f"{API}/account/articles/{aid}/reserve_doi", headers=h).raise_for_status()
104
- except Exception:
105
- pass
106
- have = _existing_files(s, h, aid)
107
- for path in attach_paths(name):
108
- if path.name in have:
109
- continue # already uploaded (resumed) -> idempotent
110
- _upload(s, h, aid, path)
111
- state[name]["done"] = True
112
- write_state("figshare", state)
113
- print(f"[figshare] ({i}/{len(names)}) {name}: DRAFT {aid}")
114
- print(f"\n[figshare] {sum(1 for r in state.values() if r.get('done'))} drafts (NONE published). Then:")
115
- print(" python publish/figshare_publish_all.py --yes")
116
-
117
-
118
- if __name__ == "__main__":
119
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/figshare_publish_all.py DELETED
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env python
2
- """Publish the 26 per-code Figshare DRAFTS created by figshare_draft.py.
3
-
4
- IRREVERSIBLE STEP. DRY RUN by default; publishes only with --yes, only the articles
5
- recorded in publish/state/figshare_drafts.json.
6
-
7
- export FIGSHARE_TOKEN=...
8
- python publish/figshare_publish_all.py # dry run
9
- python publish/figshare_publish_all.py --yes # publish
10
- """
11
- from __future__ import annotations
12
- import argparse, sys
13
- import requests
14
- from _percode import read_state, write_state, require_env
15
-
16
- API = "https://api.figshare.com/v2"
17
-
18
-
19
- def main():
20
- ap = argparse.ArgumentParser()
21
- ap.add_argument("--yes", action="store_true")
22
- args = ap.parse_args()
23
- state = read_state("figshare")
24
- pending = {n: r for n, r in state.items() if r.get("id") and not r.get("published")}
25
- if not pending:
26
- print("[figshare] no unpublished drafts in state (run figshare_draft.py first)."); return
27
- print(f"[figshare] {len(pending)} draft(s) to publish:")
28
- for n, r in pending.items():
29
- print(f" {n:9s} id={r['id']}")
30
- if not args.yes:
31
- print("\n[figshare] DRY RUN — nothing published. Re-run with --yes.")
32
- return
33
- h = {"Authorization": f"token {require_env('FIGSHARE_TOKEN')}"}
34
- s = requests.Session()
35
- for n, r in pending.items():
36
- resp = s.post(f"{API}/account/articles/{r['id']}/publish", headers=h)
37
- resp.raise_for_status()
38
- loc = resp.json().get("location", "")
39
- r["published"] = True
40
- r["public_url"] = loc
41
- write_state("figshare", state)
42
- print(f"[figshare] PUBLISHED {n}: {loc}")
43
- print(f"\n[figshare] published {len(pending)} records.")
44
-
45
-
46
- if __name__ == "__main__":
47
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/ia_upload_all.py DELETED
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env python
2
- """Upload the 26 per-code KODEX records to the Internet Archive (one item per code).
3
-
4
- NOTE: Internet Archive items become PUBLIC on upload — there is no private-draft state —
5
- so this IS the publish step for IA. DRY RUN by default; uploads only with --yes.
6
- Requires the `ia` CLI configured (`ia configure` with your S3 keys) once.
7
-
8
- python publish/ia_upload_all.py # dry run (lists items + files)
9
- python publish/ia_upload_all.py --yes # upload (public)
10
- """
11
- from __future__ import annotations
12
- import argparse, subprocess, sys
13
- from _percode import built, attach_paths, load_meta, VERSION
14
-
15
-
16
- def main():
17
- ap = argparse.ArgumentParser()
18
- ap.add_argument("--yes", action="store_true")
19
- args = ap.parse_args()
20
- names = built()
21
- print(f"[ia] {len(names)} items to upload (identifier = kronos-ml-kodex-<code>-v{VERSION}):")
22
- plans = []
23
- for name in names:
24
- m = load_meta(name)
25
- ident = f"kronos-ml-kodex-{name.lower()}-v{VERSION}"
26
- files = [str(p) for p in attach_paths(name)]
27
- plans.append((ident, m, files))
28
- print(f" {ident} ({len(files)} files)")
29
- if not args.yes:
30
- print("\n[ia] DRY RUN — nothing uploaded. Re-run with --yes (items go PUBLIC on upload).")
31
- return
32
- for ident, m, files in plans:
33
- cmd = ["ia", "upload", ident, *files,
34
- f"--metadata=title:{m['title']}",
35
- "--metadata=creator:Ford, P. I.",
36
- "--metadata=licenseurl:https://spdx.org/licenses/Apache-2.0",
37
- f"--metadata=external-identifier:{m['page']}",
38
- "--metadata=subject:fusion; spherical tokamak; AI/ML surrogate; Kronos Fusion Energy"]
39
- r = subprocess.run(cmd)
40
- if r.returncode != 0:
41
- print(f"[ia] FAILED {ident} (rc={r.returncode})"); return r.returncode
42
- print(f"[ia] uploaded https://archive.org/details/{ident}")
43
- print(f"\n[ia] uploaded {len(plans)} items.")
44
-
45
-
46
- if __name__ == "__main__":
47
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/kronos-ml-v0.1.0-source.zip DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:cc14cfb661fae0b28ebb757796c563cf9517ee3bf444e97d314cd377b4b94b21
3
- size 652545
 
 
 
 
publish/osf_draft.py DELETED
@@ -1,71 +0,0 @@
1
- #!/usr/bin/env python
2
- """Create 26 PRIVATE OSF projects (one per BUILT KODEX code).
3
-
4
- DRAFT-FIRST: each project is created private (public=false) and never made public here.
5
- Resume-safe via publish/state/osf_drafts.json. Throttled + retried against OSF's
6
- rate-limiting (403/429). After review, run osf_publish_all.py --yes.
7
-
8
- export OSF_TOKEN=...
9
- python publish/osf_draft.py
10
- """
11
- from __future__ import annotations
12
- import sys, time
13
- import requests
14
- from _percode import (built, attach_paths, load_meta, read_state, write_state,
15
- require_env, http_retry)
16
-
17
- API = "https://api.osf.io/v2"
18
- WB = "https://files.osf.io/v1"
19
- PACE_FILE = 0.6 # seconds between file uploads
20
- PACE_PROJECT = 1.2 # seconds between projects
21
-
22
-
23
- def main():
24
- token = require_env("OSF_TOKEN")
25
- h = {"Authorization": f"Bearer {token}"}
26
- hj = {**h, "Content-Type": "application/vnd.api+json"}
27
- s = requests.Session()
28
- state = read_state("osf")
29
- names = built()
30
- for i, name in enumerate(names, 1):
31
- rec = state.get(name, {})
32
- node = rec.get("id")
33
- if rec.get("done"):
34
- print(f"[osf] ({i}/{len(names)}) {name}: complete (skip)"); continue
35
- m = load_meta(name)
36
- if not node: # create the project (retry rate-limits)
37
- payload = {"data": {"type": "nodes", "attributes": {
38
- "title": m["title"], "category": "software",
39
- # OSF renders the description as PLAIN TEXT (no HTML) -> use the stripped variant
40
- "description": m.get("description_plain", m["description"]),
41
- "public": False, "tags": m["keywords"][:25]}}}
42
- r = http_retry(lambda: s.post(f"{API}/nodes/", headers=hj, json=payload),
43
- label=f"osf-create {name}")
44
- if not r.ok:
45
- print(f"[osf] {name}: create FAILED {r.status_code}: {r.text[:300]}"); return 1
46
- node = r.json()["data"]["id"]
47
- state[name] = {"id": node, "url": f"https://osf.io/{node}/"}
48
- write_state("osf", state)
49
- time.sleep(PACE_PROJECT)
50
- # upload files (throttled; 409 = already there = fine)
51
- for path in attach_paths(name):
52
- def _put():
53
- with open(path, "rb") as fh:
54
- return s.put(f"{WB}/resources/{node}/providers/osfstorage/", headers=h,
55
- params={"kind": "file", "name": path.name}, data=fh)
56
- r = http_retry(_put, label=f"osf-upload {name}/{path.name}")
57
- if r.status_code == 409:
58
- pass # file already exists (resumed) -> treat as done
59
- elif not r.ok:
60
- print(f"[osf] {name}/{path.name}: upload FAILED {r.status_code}: {r.text[:200]}")
61
- return 1
62
- time.sleep(PACE_FILE)
63
- state[name]["done"] = True
64
- write_state("osf", state)
65
- print(f"[osf] ({i}/{len(names)}) {name}: PRIVATE {node} ({len(attach_paths(name))} files)")
66
- print(f"\n[osf] {sum(1 for r in state.values() if r.get('done'))} private projects (NONE public). Then:")
67
- print(" python publish/osf_publish_all.py --yes")
68
-
69
-
70
- if __name__ == "__main__":
71
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/osf_publish_all.py DELETED
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env python
2
- """Make the 26 per-code OSF projects PUBLIC (created private by osf_draft.py).
3
-
4
- IRREVERSIBLE STEP. DRY RUN by default; flips projects to public only with --yes,
5
- and only those recorded in publish/state/osf_drafts.json.
6
-
7
- export OSF_TOKEN=...
8
- python publish/osf_publish_all.py # dry run
9
- python publish/osf_publish_all.py --yes # make public
10
- """
11
- from __future__ import annotations
12
- import argparse, sys
13
- import requests
14
- from _percode import read_state, write_state, require_env
15
-
16
- API = "https://api.osf.io/v2"
17
-
18
-
19
- def main():
20
- ap = argparse.ArgumentParser()
21
- ap.add_argument("--yes", action="store_true")
22
- args = ap.parse_args()
23
- state = read_state("osf")
24
- pending = {n: r for n, r in state.items() if r.get("id") and not r.get("public")}
25
- if not pending:
26
- print("[osf] no private projects in state (run osf_draft.py first)."); return
27
- print(f"[osf] {len(pending)} project(s) to make public:")
28
- for n, r in pending.items():
29
- print(f" {n:9s} {r.get('url','')}")
30
- if not args.yes:
31
- print("\n[osf] DRY RUN — nothing made public. Re-run with --yes.")
32
- return
33
- hj = {"Authorization": f"Bearer {require_env('OSF_TOKEN')}",
34
- "Content-Type": "application/vnd.api+json"}
35
- s = requests.Session()
36
- for n, r in pending.items():
37
- payload = {"data": {"type": "nodes", "id": r["id"], "attributes": {"public": True}}}
38
- resp = s.patch(f"{API}/nodes/{r['id']}/", headers=hj, json=payload)
39
- resp.raise_for_status()
40
- r["public"] = True
41
- write_state("osf", state)
42
- print(f"[osf] PUBLIC {n}: {r.get('url')}")
43
- print(f"\n[osf] made {len(pending)} projects public.")
44
-
45
-
46
- if __name__ == "__main__":
47
- sys.exit(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kairos/CITATION.cff DELETED
@@ -1,13 +0,0 @@
1
- cff-version: 1.2.0
2
- title: "KODEX — KAIROS: CONTROL (Kronos Family of Codes)"
3
- version: "0.2.0"
4
- date-released: "2026-09-11"
5
- license: Apache-2.0
6
- url: "https://kronosfusionenergy.com/kodex/kairos"
7
- repository-code: "https://github.com/KronosFE/kronos-ml"
8
- type: software
9
- authors:
10
- - family-names: Ford
11
- given-names: "P. I."
12
- orcid: "https://orcid.org/0000-0003-0395-1752"
13
- affiliation: "Kronos Fusion Energy"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kairos/LICENSE DELETED
@@ -1,189 +0,0 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but not
32
- limited to compiled object code, generated documentation, and
33
- conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work.
38
-
39
- "Derivative Works" shall mean any work, whether in Source or Object
40
- form, that is based on (or derived from) the Work and for which the
41
- editorial revisions, annotations, elaborations, or other modifications
42
- represent, as a whole, an original work of authorship. For the purposes
43
- of this License, Derivative Works shall not include works that remain
44
- separable from, or merely link (or bind by name) to the interfaces of,
45
- the Work and Derivative Works thereof.
46
-
47
- "Contribution" shall mean any work of authorship, including the
48
- original version of the Work and any modifications or additions
49
- to that Work or Derivative Works thereof, that is intentionally
50
- submitted to Licensor for inclusion in the Work by the copyright owner
51
- or by an individual or Legal Entity authorized to submit on behalf of
52
- the copyright owner. For the purposes of this definition, "submitted"
53
- means any form of electronic, verbal, or written communication sent
54
- to the Licensor or its representatives, including but not limited to
55
- communication on electronic mailing lists, source code control systems,
56
- and issue tracking systems that are managed by, or on behalf of, the
57
- Licensor for the purpose of discussing and improving the Work, but
58
- excluding communication that is conspicuously marked or otherwise
59
- designated in writing by the copyright owner as "Not a Contribution."
60
-
61
- "Contributor" shall mean Licensor and any individual or Legal Entity
62
- on behalf of whom a Contribution has been received by Licensor and
63
- subsequently incorporated within the Work.
64
-
65
- 2. Grant of Copyright License. Subject to the terms and conditions of
66
- this License, each Contributor hereby grants to You a perpetual,
67
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
68
- copyright license to reproduce, prepare Derivative Works of,
69
- publicly display, publicly perform, sublicense, and distribute the
70
- Work and such Derivative Works in Source or Object form.
71
-
72
- 3. Grant of Patent License. Subject to the terms and conditions of
73
- this License, each Contributor hereby grants to You a perpetual,
74
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
75
- (except as stated in this section) patent license to make, have made,
76
- use, offer to sell, sell, import, and otherwise transfer the Work,
77
- where such license applies only to those patent claims licensable
78
- by such Contributor that are necessarily infringed by their
79
- Contribution(s) alone or by combination of their Contribution(s)
80
- with the Work to which such Contribution(s) was submitted. If You
81
- institute patent litigation against any entity (including a
82
- cross-claim or counterclaim in a lawsuit) alleging that the Work
83
- or a Contribution incorporated within the Work constitutes direct
84
- or contributory patent infringement, then any patent licenses
85
- granted to You under this License for that Work shall terminate
86
- as of the date such litigation is filed.
87
-
88
- 4. Redistribution. You may reproduce and distribute copies of the
89
- Work or Derivative Works thereof in any medium, with or without
90
- modifications, and in Source or Object form, provided that You
91
- meet the following conditions:
92
-
93
- (a) You must give any other recipients of the Work or Derivative
94
- Works a copy of this License; and
95
-
96
- (b) You must cause any modified files to carry prominent notices
97
- stating that You changed the files; and
98
-
99
- (c) You must retain, in the Source form of any Derivative Works
100
- that You distribute, all copyright, patent, trademark, and
101
- attribution notices from the Source form of the Work,
102
- excluding those notices that do not pertain to any part of
103
- the Derivative Works; and
104
-
105
- (d) If the Work includes a "NOTICE" text file as part of its
106
- distribution, then any Derivative Works that You distribute must
107
- include a readable copy of the attribution notices contained
108
- within such NOTICE file, excluding those notices that do not
109
- pertain to any part of the Derivative Works.
110
-
111
- You may add Your own copyright statement to Your modifications and
112
- may provide additional or different license terms and conditions
113
- for use, reproduction, or distribution of Your modifications, or
114
- for any such Derivative Works as a whole, provided Your use,
115
- reproduction, and distribution of the Work otherwise complies with
116
- the conditions stated in this License.
117
-
118
- 5. Submission of Contributions. Unless You explicitly state otherwise,
119
- any Contribution intentionally submitted for inclusion in the Work
120
- by You to the Licensor shall be under the terms and conditions of
121
- this License, without any additional terms or conditions.
122
- Notwithstanding the above, nothing herein shall supersede or modify
123
- the terms of any separate license agreement you may have executed
124
- with Licensor regarding such Contributions.
125
-
126
- 6. Trademarks. This License does not grant permission to use the trade
127
- names, trademarks, service marks, or product names of the Licensor,
128
- except as required for reasonable and customary use in describing the
129
- origin of the Work and reproducing the content of the NOTICE file.
130
-
131
- 7. Disclaimer of Warranty. Unless required by applicable law or
132
- agreed to in writing, Licensor provides the Work (and each
133
- Contributor provides its Contributions) on an "AS IS" BASIS,
134
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
135
- implied, including, without limitation, any warranties or conditions
136
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
137
- PARTICULAR PURPOSE. You are solely responsible for determining the
138
- appropriateness of using or redistributing the Work and assume any
139
- risks associated with Your exercise of permissions under this License.
140
-
141
- 8. Limitation of Liability. In no event and under no legal theory,
142
- whether in tort (including negligence), contract, or otherwise,
143
- unless required by applicable law (such as deliberate and grossly
144
- negligent acts) or agreed to in writing, shall any Contributor be
145
- liable to You for damages, including any direct, indirect, special,
146
- incidental, or consequential damages of any character arising as a
147
- result of this License or out of the use or inability to use the
148
- Work (including but not limited to damages for loss of goodwill,
149
- work stoppage, computer failure or malfunction, or any and all
150
- other commercial damages or losses), even if such Contributor
151
- has been advised of the possibility of such damages.
152
-
153
- 9. Accepting Warranty or Additional Liability. While redistributing
154
- the Work or Derivative Works thereof, You may choose to offer,
155
- and charge a fee for, acceptance of support, warranty, indemnity,
156
- or other liability obligations and/or rights consistent with this
157
- License. However, in accepting such obligations, You may act only
158
- on Your own behalf and on Your sole responsibility, not on behalf
159
- of any other Contributor, and only if You agree to indemnify,
160
- defend, and hold each Contributor harmless for any liability
161
- incurred by, or claims asserted against, such Contributor by reason
162
- of your accepting any such warranty or additional liability.
163
-
164
- END OF TERMS AND CONDITIONS
165
-
166
- APPENDIX: How to apply the Apache License to your work.
167
-
168
- To apply the Apache License to your work, attach the following
169
- boilerplate notice, with the fields enclosed by brackets "[]"
170
- replaced with your own identifying information. (Don't include
171
- the brackets!) The text should be enclosed in the appropriate
172
- comment syntax for the file format. We also recommend that a
173
- file or class name and description of purpose be included on the
174
- same "printed page" as the copyright notice for easier
175
- identification within third-party archives.
176
-
177
- Copyright 2026 Kronos Fusion Energy
178
-
179
- Licensed under the Apache License, Version 2.0 (the "License");
180
- you may not use this file except in compliance with the License.
181
- You may obtain a copy of the License at
182
-
183
- http://www.apache.org/licenses/LICENSE-2.0
184
-
185
- Unless required by applicable law or agreed to in writing, software
186
- distributed under the License is distributed on an "AS IS" BASIS,
187
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
188
- See the License for the specific language governing permissions and
189
- limitations under the License.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kairos/MANIFEST.sha256 DELETED
@@ -1,7 +0,0 @@
1
- # KODEX KAIROS SHA-256 (0.2.0, 2026-09-11)
2
- d334149c67e6fab06da1157e5cd47129d2bf4e738754afeb20176b6bacb89d54 CITATION.cff
3
- ae87ebecd1f321a19799e21f6fe25e4a74261f16c91e6cb6cc248e6197dcf838 LICENSE
4
- 4519abc8cba84d5ba68e5e0cc5faef0dac4094a970a6a4a39f993abcfc4931be benchmark.json
5
- f99514c0fb9ad18571bfafcdd8579f51323285a65c66f90140d91cb781a58243 card.md
6
- 203323e21eb15172090486e0fdde9367a3c13b7e1fb3d66d5b280108b7f15f32 kairos.py
7
- 85ff663bac08f45a66d216dbbed1bf62143b7fa0943192c6f6e91f4ca3cf4c47 metadata.json
 
 
 
 
 
 
 
 
publish/records/kairos/benchmark.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "member": "KAIROS",
3
- "live_tracking_rms_frac": 0.0461,
4
- "live_expB_model_failure": {
5
- "adversaries": [
6
- "drift",
7
- "edge_seeker",
8
- "nan_garbage"
9
- ],
10
- "steps": 150000,
11
- "escapes": 0,
12
- "catch_rate": 1.0
13
- },
14
- "live_mpc_step_us": 96.1,
15
- "sourced": {
16
- "file": "track5_control/clamp_activation_stats.csv",
17
- "headline": "0 escapes / 150k steps / 3000 injected (AC-25); tracking <5%"
18
- }
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kairos/card.md DELETED
@@ -1,13 +0,0 @@
1
- # KODEX KAIROS — card
2
-
3
- - **name:** KAIROS
4
- - **function:** CONTROL
5
- - **status:** BUILT
6
- - **phase:** 1
7
- - **provenance:** TWIN
8
- - **retired_by:** validated real-time plant controller (device-in-the-loop)
9
- - **gates:** ['AC-24', 'AC-25']
10
- - **note:** real-time closed-loop MPC control (analytic finite-horizon QP); supplies the model-free L4 clamp that KGATE enforces
11
- - **available:** True
12
-
13
- Benchmark headline: MPC tracking 0.0461 (<5%); Exp-B **0 escapes / 150,000**; 96.1 µs/step
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kairos/kairos.py DELETED
@@ -1,57 +0,0 @@
1
- """KODEX KAIROS — source excerpt (class). Full runnable package: https://github.com/KronosFE/kronos-ml"""
2
-
3
- @register
4
- class KAIROS(Surrogate):
5
- name = "KAIROS"; function = "CONTROL"; phase = 1; status = "BUILT"
6
- provenance = "TWIN"
7
- retired_by = "validated real-time plant controller (device-in-the-loop)"
8
- real_codes = ("receding-horizon MPC",)
9
- gates = ("AC-24", "AC-25")
10
- note = ("real-time closed-loop MPC control (analytic finite-horizon QP); "
11
- "supplies the model-free L4 clamp that KGATE enforces")
12
-
13
- def _predict(self, x):
14
- """x = (state6, ref6) -> next command from the MPC, clamped by KGATE."""
15
- state, ref = x
16
- u = _mpc(state, ref)
17
- safe, ok = get("KGATE").clamp(u)
18
- in_dom = bool(np.allclose(safe, u, atol=1e-6))
19
- return Prediction(safe, None, in_dom,
20
- note="MPC step, clamped" if not in_dom else "MPC step, in envelope")
21
-
22
- def benchmark(self):
23
- rng = np.random.default_rng(uq.SEED)
24
- clamp = get("KGATE").clamp
25
- # (1) closed-loop tracking: drive from a start state to a setpoint
26
- ref = np.array([2.2, 0.3, 3.0, 1.0, 0.2, 30.0])
27
- x = np.array([2.0, 0.0, 2.0, 0.5, 0.1, 20.0])
28
- for _ in range(200):
29
- safe, _ = clamp(_mpc(x, ref)); x = _plant_step(x, safe, rng)
30
- rng_scale = np.array([1, 1, 4.2, 3, 0.4, 47.21])
31
- track_rms = float(np.sqrt(np.mean(((x - ref) / rng_scale) ** 2)))
32
- # (2) Exp-B: broken controllers emit unsafe commands; clamp must catch all
33
- from .spine import _LO, _HI
34
- adversaries = {
35
- "drift": lambda: _HI * (1 + 0.5 * rng.random(6)),
36
- "edge_seeker": lambda: _HI + 5,
37
- "nan_garbage": lambda: np.where(rng.random(6) < 0.3, np.nan, _HI * 3),
38
- }
39
- escapes = 0; steps = 0
40
- for _, gen in adversaries.items():
41
- for _ in range(50_000):
42
- safe, _ = clamp(gen()); steps += 1
43
- if not (np.all(safe >= _LO - 1e-9) and np.all(safe <= _HI + 1e-9)):
44
- escapes += 1
45
- # (3) real latency of an MPC step + clamp
46
- t0 = time.perf_counter()
47
- for _ in range(2000):
48
- clamp(_mpc(x, ref))
49
- us = (time.perf_counter() - t0) / 2000 * 1e6
50
- return {"member": self.name,
51
- "live_tracking_rms_frac": round(track_rms, 4),
52
- "live_expB_model_failure": {"adversaries": list(adversaries),
53
- "steps": steps, "escapes": escapes,
54
- "catch_rate": 1.0 - escapes / steps},
55
- "live_mpc_step_us": round(us, 1),
56
- "sourced": {"file": "track5_control/clamp_activation_stats.csv",
57
- "headline": "0 escapes / 150k steps / 3000 injected (AC-25); tracking <5%"}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kairos/metadata.json DELETED
@@ -1,65 +0,0 @@
1
- {
2
- "kname": "KAIROS",
3
- "page": "https://kronosfusionenergy.com/kodex/kairos",
4
- "title": "KODEX \u2014 KAIROS: CONTROL",
5
- "version": "0.2.0",
6
- "publication_date": "2026-09-11",
7
- "language": "eng",
8
- "upload_type": "software",
9
- "creators": [
10
- {
11
- "name": "Ford, P. I.",
12
- "orcid": "0000-0003-0395-1752",
13
- "affiliation": "Kronos Fusion Energy"
14
- }
15
- ],
16
- "license": {
17
- "id": "Apache-2.0"
18
- },
19
- "keywords": [
20
- "fusion energy",
21
- "spherical tokamak",
22
- "D-3He",
23
- "AI/ML surrogate model",
24
- "uncertainty quantification",
25
- "digital twin",
26
- "Kronos Fusion Energy",
27
- "CONTROL",
28
- "KODEX:KAIROS"
29
- ],
30
- "related_identifiers": [
31
- {
32
- "relation": "isDocumentedBy",
33
- "identifier": "https://kronosfusionenergy.com/kodex/kairos",
34
- "resource_type": "publication-other"
35
- },
36
- {
37
- "relation": "isPartOf",
38
- "identifier": "https://kronosfusionenergy.com/kodex",
39
- "resource_type": "publication-other"
40
- },
41
- {
42
- "relation": "isSupplementTo",
43
- "identifier": "https://github.com/KronosFE/kronos-ml",
44
- "resource_type": "software"
45
- },
46
- {
47
- "relation": "references",
48
- "identifier": "10.5281/zenodo.22645689",
49
- "resource_type": "publication"
50
- },
51
- {
52
- "relation": "isCompiledBy",
53
- "identifier": "https://github.com/KronosFE/kronos-toolkit",
54
- "resource_type": "software"
55
- },
56
- {
57
- "relation": "references",
58
- "identifier": "10.5281/zenodo.21842371",
59
- "resource_type": "dataset"
60
- }
61
- ],
62
- "description": "<p><strong>KODEX &mdash; KAIROS</strong> (CONTROL). real-time closed-loop MPC control (analytic finite-horizon QP); supplies the model-free L4 clamp that KGATE enforces</p><p><strong>Benchmark:</strong> MPC tracking 0.0461 (<5%); Exp-B **0 escapes / 150,000**; 96.1 \u00b5s/step</p><p>Part of KODEX, the Kronos Family of Codes &mdash; a benchmarked AI/ML fusion surrogate suite with calibrated uncertainty and an abstention gate (<code>predict(x) &rarr; (y, uncertainty, in_domain)</code>). Provenance: references 10.5281/zenodo.21842371. Home: <a href=\"https://kronosfusionenergy.com/kodex/kairos\">https://kronosfusionenergy.com/kodex/kairos</a> &middot; suite: <a href=\"https://github.com/KronosFE/kronos-ml\">https://github.com/KronosFE/kronos-ml</a>. Licensed under Apache-2.0. Honest card preserved verbatim.</p>",
63
- "description_plain": "KODEX \u2014 KAIROS (CONTROL). real-time closed-loop MPC control (analytic finite-horizon QP); supplies the model-free L4 clamp that KGATE enforcesBenchmark: MPC tracking 0.0461 (Part of KODEX, the Kronos Family of Codes \u2014 a benchmarked AI/ML fusion surrogate suite with calibrated uncertainty and an abstention gate (predict(x) \u2192 (y, uncertainty, in_domain)). Provenance: references 10.5281/zenodo.21842371. Home: https://kronosfusionenergy.com/kodex/kairos \u00b7 suite: https://github.com/KronosFE/kronos-ml. Licensed under Apache-2.0. Honest card preserved verbatim.",
64
- "notes": "Draft-first per-code deposit. Full package (all 26 codes): https://github.com/KronosFE/kronos-ml. Provenance chain in card.md + MANIFEST.sha256."
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kbench/CITATION.cff DELETED
@@ -1,13 +0,0 @@
1
- cff-version: 1.2.0
2
- title: "KODEX — KBENCH: BENCHMARK (Kronos Family of Codes)"
3
- version: "0.2.0"
4
- date-released: "2026-09-11"
5
- license: Apache-2.0
6
- url: "https://kronosfusionenergy.com/kodex/kbench"
7
- repository-code: "https://github.com/KronosFE/kronos-ml"
8
- type: software
9
- authors:
10
- - family-names: Ford
11
- given-names: "P. I."
12
- orcid: "https://orcid.org/0000-0003-0395-1752"
13
- affiliation: "Kronos Fusion Energy"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kbench/LICENSE DELETED
@@ -1,189 +0,0 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but not
32
- limited to compiled object code, generated documentation, and
33
- conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work.
38
-
39
- "Derivative Works" shall mean any work, whether in Source or Object
40
- form, that is based on (or derived from) the Work and for which the
41
- editorial revisions, annotations, elaborations, or other modifications
42
- represent, as a whole, an original work of authorship. For the purposes
43
- of this License, Derivative Works shall not include works that remain
44
- separable from, or merely link (or bind by name) to the interfaces of,
45
- the Work and Derivative Works thereof.
46
-
47
- "Contribution" shall mean any work of authorship, including the
48
- original version of the Work and any modifications or additions
49
- to that Work or Derivative Works thereof, that is intentionally
50
- submitted to Licensor for inclusion in the Work by the copyright owner
51
- or by an individual or Legal Entity authorized to submit on behalf of
52
- the copyright owner. For the purposes of this definition, "submitted"
53
- means any form of electronic, verbal, or written communication sent
54
- to the Licensor or its representatives, including but not limited to
55
- communication on electronic mailing lists, source code control systems,
56
- and issue tracking systems that are managed by, or on behalf of, the
57
- Licensor for the purpose of discussing and improving the Work, but
58
- excluding communication that is conspicuously marked or otherwise
59
- designated in writing by the copyright owner as "Not a Contribution."
60
-
61
- "Contributor" shall mean Licensor and any individual or Legal Entity
62
- on behalf of whom a Contribution has been received by Licensor and
63
- subsequently incorporated within the Work.
64
-
65
- 2. Grant of Copyright License. Subject to the terms and conditions of
66
- this License, each Contributor hereby grants to You a perpetual,
67
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
68
- copyright license to reproduce, prepare Derivative Works of,
69
- publicly display, publicly perform, sublicense, and distribute the
70
- Work and such Derivative Works in Source or Object form.
71
-
72
- 3. Grant of Patent License. Subject to the terms and conditions of
73
- this License, each Contributor hereby grants to You a perpetual,
74
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
75
- (except as stated in this section) patent license to make, have made,
76
- use, offer to sell, sell, import, and otherwise transfer the Work,
77
- where such license applies only to those patent claims licensable
78
- by such Contributor that are necessarily infringed by their
79
- Contribution(s) alone or by combination of their Contribution(s)
80
- with the Work to which such Contribution(s) was submitted. If You
81
- institute patent litigation against any entity (including a
82
- cross-claim or counterclaim in a lawsuit) alleging that the Work
83
- or a Contribution incorporated within the Work constitutes direct
84
- or contributory patent infringement, then any patent licenses
85
- granted to You under this License for that Work shall terminate
86
- as of the date such litigation is filed.
87
-
88
- 4. Redistribution. You may reproduce and distribute copies of the
89
- Work or Derivative Works thereof in any medium, with or without
90
- modifications, and in Source or Object form, provided that You
91
- meet the following conditions:
92
-
93
- (a) You must give any other recipients of the Work or Derivative
94
- Works a copy of this License; and
95
-
96
- (b) You must cause any modified files to carry prominent notices
97
- stating that You changed the files; and
98
-
99
- (c) You must retain, in the Source form of any Derivative Works
100
- that You distribute, all copyright, patent, trademark, and
101
- attribution notices from the Source form of the Work,
102
- excluding those notices that do not pertain to any part of
103
- the Derivative Works; and
104
-
105
- (d) If the Work includes a "NOTICE" text file as part of its
106
- distribution, then any Derivative Works that You distribute must
107
- include a readable copy of the attribution notices contained
108
- within such NOTICE file, excluding those notices that do not
109
- pertain to any part of the Derivative Works.
110
-
111
- You may add Your own copyright statement to Your modifications and
112
- may provide additional or different license terms and conditions
113
- for use, reproduction, or distribution of Your modifications, or
114
- for any such Derivative Works as a whole, provided Your use,
115
- reproduction, and distribution of the Work otherwise complies with
116
- the conditions stated in this License.
117
-
118
- 5. Submission of Contributions. Unless You explicitly state otherwise,
119
- any Contribution intentionally submitted for inclusion in the Work
120
- by You to the Licensor shall be under the terms and conditions of
121
- this License, without any additional terms or conditions.
122
- Notwithstanding the above, nothing herein shall supersede or modify
123
- the terms of any separate license agreement you may have executed
124
- with Licensor regarding such Contributions.
125
-
126
- 6. Trademarks. This License does not grant permission to use the trade
127
- names, trademarks, service marks, or product names of the Licensor,
128
- except as required for reasonable and customary use in describing the
129
- origin of the Work and reproducing the content of the NOTICE file.
130
-
131
- 7. Disclaimer of Warranty. Unless required by applicable law or
132
- agreed to in writing, Licensor provides the Work (and each
133
- Contributor provides its Contributions) on an "AS IS" BASIS,
134
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
135
- implied, including, without limitation, any warranties or conditions
136
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
137
- PARTICULAR PURPOSE. You are solely responsible for determining the
138
- appropriateness of using or redistributing the Work and assume any
139
- risks associated with Your exercise of permissions under this License.
140
-
141
- 8. Limitation of Liability. In no event and under no legal theory,
142
- whether in tort (including negligence), contract, or otherwise,
143
- unless required by applicable law (such as deliberate and grossly
144
- negligent acts) or agreed to in writing, shall any Contributor be
145
- liable to You for damages, including any direct, indirect, special,
146
- incidental, or consequential damages of any character arising as a
147
- result of this License or out of the use or inability to use the
148
- Work (including but not limited to damages for loss of goodwill,
149
- work stoppage, computer failure or malfunction, or any and all
150
- other commercial damages or losses), even if such Contributor
151
- has been advised of the possibility of such damages.
152
-
153
- 9. Accepting Warranty or Additional Liability. While redistributing
154
- the Work or Derivative Works thereof, You may choose to offer,
155
- and charge a fee for, acceptance of support, warranty, indemnity,
156
- or other liability obligations and/or rights consistent with this
157
- License. However, in accepting such obligations, You may act only
158
- on Your own behalf and on Your sole responsibility, not on behalf
159
- of any other Contributor, and only if You agree to indemnify,
160
- defend, and hold each Contributor harmless for any liability
161
- incurred by, or claims asserted against, such Contributor by reason
162
- of your accepting any such warranty or additional liability.
163
-
164
- END OF TERMS AND CONDITIONS
165
-
166
- APPENDIX: How to apply the Apache License to your work.
167
-
168
- To apply the Apache License to your work, attach the following
169
- boilerplate notice, with the fields enclosed by brackets "[]"
170
- replaced with your own identifying information. (Don't include
171
- the brackets!) The text should be enclosed in the appropriate
172
- comment syntax for the file format. We also recommend that a
173
- file or class name and description of purpose be included on the
174
- same "printed page" as the copyright notice for easier
175
- identification within third-party archives.
176
-
177
- Copyright 2026 Kronos Fusion Energy
178
-
179
- Licensed under the Apache License, Version 2.0 (the "License");
180
- you may not use this file except in compliance with the License.
181
- You may obtain a copy of the License at
182
-
183
- http://www.apache.org/licenses/LICENSE-2.0
184
-
185
- Unless required by applicable law or agreed to in writing, software
186
- distributed under the License is distributed on an "AS IS" BASIS,
187
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
188
- See the License for the specific language governing permissions and
189
- limitations under the License.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kbench/MANIFEST.sha256 DELETED
@@ -1,7 +0,0 @@
1
- # KODEX KBENCH SHA-256 (0.2.0, 2026-09-11)
2
- cecfe7657f26a4b4af96f4257070e8769c4c9266748d8717f4ceeb3fbba00e83 CITATION.cff
3
- ae87ebecd1f321a19799e21f6fe25e4a74261f16c91e6cb6cc248e6197dcf838 LICENSE
4
- 1f532ca6a582bc0e639f3490dc421c799f583766a8639863078d00ff3ef66f75 benchmark.json
5
- 65f7c48c499563e291bf9230ac6098dcee186eaf437e97b43b41a640638fa972 card.md
6
- 4d0e21b1012d27a9f9a2bb6cccb937530a8efe1ed02b6b9d5cc569ac8ad42c91 kbench.py
7
- e62bf7f72ba3ffda7478ade5c404e054bb0e77d9a42be30352ef1952673934a4 metadata.json
 
 
 
 
 
 
 
 
publish/records/kbench/benchmark.json DELETED
@@ -1,44 +0,0 @@
1
- {
2
- "member": "KBENCH",
3
- "live_benchmark_suite": {
4
- "n_tasks": 3,
5
- "tasks": {
6
- "cgyro-turbulence-flux": {
7
- "inputs": [
8
- "a_LT",
9
- "shear"
10
- ],
11
- "target": "log10 Q_tot (regression) + turbulent/quiet (classification)",
12
- "n_samples": 16,
13
- "metric": "R2 (regression) / leave-one-out accuracy (classification)",
14
- "loader": "kronos_ml.data.cgyro_flux_map_final()",
15
- "baseline_code": "KYRO",
16
- "baseline_score": "R2 ~0.86, turbulent/quiet 16/16",
17
- "note": "real CGYRO A1e saturated-flux (mu=400 representative)"
18
- },
19
- "mast-disruption": {
20
- "inputs": "physics features (Ip family + EFIT + n=1 Mirnov / P_rad)",
21
- "target": "disruptive (binary)",
22
- "n_samples": 591,
23
- "metric": "ROC-AUC (+ independent-precursor AUC)",
24
- "loader": "kronos_ml.data.kward_real()",
25
- "baseline_code": "KWARD",
26
- "baseline_score": "AUC ~0.98, independent-precursor 0.975",
27
- "note": "real MAST shots (FAIR-MAST); labels are heuristic Ip-quench"
28
- },
29
- "cgyro-rom-compressibility": {
30
- "inputs": "flux-database matrix (points x [inputs, fluxes])",
31
- "target": "rel-L2 reconstruction error vs retained bond dimension",
32
- "n_samples": 16,
33
- "metric": "rel-L2 vs rank",
34
- "loader": "kronos_ml.data.cgyro_flux_map_final()",
35
- "baseline_code": "KTENSOR",
36
- "baseline_score": "effective rank 2.93/4 (not strongly low-rank)",
37
- "note": "honest ROM characterization"
38
- }
39
- },
40
- "how_to_use": "load via each task's loader, use the fixed reproducible split, report the metric, and try to beat the named KODEX baseline_code",
41
- "verdict": "3 open, citable fusion-ML tasks (CGYRO turbulence, MAST disruption, flux ROM) with real on-disk data + reproducible KODEX baselines \u2014 a community leaderboard starting point, not a private result"
42
- },
43
- "caveat": "small by mainstream-ML standards (CGYRO = 16 pts); honest pilot fusion-ML benchmarks"
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kbench/card.md DELETED
@@ -1,13 +0,0 @@
1
- # KODEX KBENCH — card
2
-
3
- - **name:** KBENCH
4
- - **function:** BENCHMARK
5
- - **status:** BUILT
6
- - **phase:** 3
7
- - **provenance:** n/a
8
- - **retired_by:** community-standard fusion-ML benchmarks
9
- - **gates:** []
10
- - **note:** open, citable ML benchmark suite for fusion — real CGYRO turbulence + MAST disruption tasks with fixed splits, metrics and KODEX baselines to beat. Bring your own model; move the community forward
11
- - **available:** True
12
-
13
- Benchmark headline: open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselines
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kbench/kbench.py DELETED
@@ -1,54 +0,0 @@
1
- """KODEX KBENCH — source excerpt (class). Full runnable package: https://github.com/KronosFE/kronos-ml"""
2
-
3
- @register
4
- class KBENCH(Surrogate):
5
- name = "KBENCH"; function = "BENCHMARK"; phase = 3; status = "BUILT"
6
- provenance = "n/a"
7
- retired_by = "community-standard fusion-ML benchmarks"
8
- real_codes = ("open ML benchmark suite",)
9
- gates = ()
10
- note = ("open, citable ML benchmark suite for fusion — real CGYRO turbulence + MAST "
11
- "disruption tasks with fixed splits, metrics and KODEX baselines to beat. Bring "
12
- "your own model; move the community forward")
13
-
14
- def tasks(self):
15
- return {
16
- "cgyro-turbulence-flux": {
17
- "inputs": ["a_LT", "shear"],
18
- "target": "log10 Q_tot (regression) + turbulent/quiet (classification)",
19
- "n_samples": 16, "metric": "R2 (regression) / leave-one-out accuracy (classification)",
20
- "loader": "kronos_ml.data.cgyro_flux_map_final()",
21
- "baseline_code": "KYRO", "baseline_score": "R2 ~0.86, turbulent/quiet 16/16",
22
- "note": "real CGYRO A1e saturated-flux (mu=400 representative)"},
23
- "mast-disruption": {
24
- "inputs": "physics features (Ip family + EFIT + n=1 Mirnov / P_rad)",
25
- "target": "disruptive (binary)",
26
- "n_samples": 591, "metric": "ROC-AUC (+ independent-precursor AUC)",
27
- "loader": "kronos_ml.data.kward_real()",
28
- "baseline_code": "KWARD", "baseline_score": "AUC ~0.98, independent-precursor 0.975",
29
- "note": "real MAST shots (FAIR-MAST); labels are heuristic Ip-quench"},
30
- "cgyro-rom-compressibility": {
31
- "inputs": "flux-database matrix (points x [inputs, fluxes])",
32
- "target": "rel-L2 reconstruction error vs retained bond dimension",
33
- "n_samples": 16, "metric": "rel-L2 vs rank",
34
- "loader": "kronos_ml.data.cgyro_flux_map_final()",
35
- "baseline_code": "KTENSOR", "baseline_score": "effective rank 2.93/4 (not strongly low-rank)",
36
- "note": "honest ROM characterization"},
37
- }
38
-
39
- def _predict(self, x):
40
- t = self.tasks()
41
- key = x if isinstance(x, str) and x in t else next(iter(t))
42
- return Prediction(t[key], None, True, note=f"fusion-ML benchmark task spec: {key}")
43
-
44
- def benchmark(self):
45
- t = self.tasks()
46
- return {"member": self.name,
47
- "live_benchmark_suite": {
48
- "n_tasks": len(t), "tasks": t,
49
- "how_to_use": ("load via each task's loader, use the fixed reproducible split, report "
50
- "the metric, and try to beat the named KODEX baseline_code"),
51
- "verdict": ("3 open, citable fusion-ML tasks (CGYRO turbulence, MAST disruption, flux "
52
- "ROM) with real on-disk data + reproducible KODEX baselines — a community "
53
- "leaderboard starting point, not a private result")},
54
- "caveat": "small by mainstream-ML standards (CGYRO = 16 pts); honest pilot fusion-ML benchmarks"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kbench/metadata.json DELETED
@@ -1,65 +0,0 @@
1
- {
2
- "kname": "KBENCH",
3
- "page": "https://kronosfusionenergy.com/kodex/kbench",
4
- "title": "KODEX \u2014 KBENCH: BENCHMARK",
5
- "version": "0.2.0",
6
- "publication_date": "2026-09-11",
7
- "language": "eng",
8
- "upload_type": "software",
9
- "creators": [
10
- {
11
- "name": "Ford, P. I.",
12
- "orcid": "0000-0003-0395-1752",
13
- "affiliation": "Kronos Fusion Energy"
14
- }
15
- ],
16
- "license": {
17
- "id": "Apache-2.0"
18
- },
19
- "keywords": [
20
- "fusion energy",
21
- "spherical tokamak",
22
- "D-3He",
23
- "AI/ML surrogate model",
24
- "uncertainty quantification",
25
- "digital twin",
26
- "Kronos Fusion Energy",
27
- "BENCHMARK",
28
- "KODEX:KBENCH"
29
- ],
30
- "related_identifiers": [
31
- {
32
- "relation": "isDocumentedBy",
33
- "identifier": "https://kronosfusionenergy.com/kodex/kbench",
34
- "resource_type": "publication-other"
35
- },
36
- {
37
- "relation": "isPartOf",
38
- "identifier": "https://kronosfusionenergy.com/kodex",
39
- "resource_type": "publication-other"
40
- },
41
- {
42
- "relation": "isSupplementTo",
43
- "identifier": "https://github.com/KronosFE/kronos-ml",
44
- "resource_type": "software"
45
- },
46
- {
47
- "relation": "references",
48
- "identifier": "10.5281/zenodo.22645689",
49
- "resource_type": "publication"
50
- },
51
- {
52
- "relation": "isCompiledBy",
53
- "identifier": "https://github.com/KronosFE/kronos-toolkit",
54
- "resource_type": "software"
55
- },
56
- {
57
- "relation": "references",
58
- "identifier": "10.5281/zenodo.21842371",
59
- "resource_type": "dataset"
60
- }
61
- ],
62
- "description": "<p><strong>KODEX &mdash; KBENCH</strong> (BENCHMARK). open, citable ML benchmark suite for fusion \u2014 real CGYRO turbulence + MAST disruption tasks with fixed splits, metrics and KODEX baselines to beat. Bring your own model; move the community forward</p><p><strong>Benchmark:</strong> open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselines</p><p>Part of KODEX, the Kronos Family of Codes &mdash; a benchmarked AI/ML fusion surrogate suite with calibrated uncertainty and an abstention gate (<code>predict(x) &rarr; (y, uncertainty, in_domain)</code>). Provenance: references 10.5281/zenodo.21842371. Home: <a href=\"https://kronosfusionenergy.com/kodex/kbench\">https://kronosfusionenergy.com/kodex/kbench</a> &middot; suite: <a href=\"https://github.com/KronosFE/kronos-ml\">https://github.com/KronosFE/kronos-ml</a>. Licensed under Apache-2.0. Honest card preserved verbatim.</p>",
63
- "description_plain": "KODEX \u2014 KBENCH (BENCHMARK). open, citable ML benchmark suite for fusion \u2014 real CGYRO turbulence + MAST disruption tasks with fixed splits, metrics and KODEX baselines to beat. Bring your own model; move the community forwardBenchmark: open fusion-ML benchmark suite: **3 citable tasks** (CGYRO turbulence, MAST disruption, flux ROM) with real data + KODEX baselinesPart of KODEX, the Kronos Family of Codes \u2014 a benchmarked AI/ML fusion surrogate suite with calibrated uncertainty and an abstention gate (predict(x) \u2192 (y, uncertainty, in_domain)). Provenance: references 10.5281/zenodo.21842371. Home: https://kronosfusionenergy.com/kodex/kbench \u00b7 suite: https://github.com/KronosFE/kronos-ml. Licensed under Apache-2.0. Honest card preserved verbatim.",
64
- "notes": "Draft-first per-code deposit. Full package: https://github.com/KronosFE/kronos-ml. Provenance chain in card.md + MANIFEST.sha256."
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
publish/records/kbreed/CITATION.cff DELETED
@@ -1,13 +0,0 @@
1
- cff-version: 1.2.0
2
- title: "KODEX — KBREED: breeder (Kronos Family of Codes)"
3
- version: "0.2.0"
4
- date-released: "2026-09-11"
5
- license: Apache-2.0
6
- url: "https://kronosfusionenergy.com/kodex/kbreed"
7
- repository-code: "https://github.com/KronosFE/kronos-ml"
8
- type: software
9
- authors:
10
- - family-names: Ford
11
- given-names: "P. I."
12
- orcid: "https://orcid.org/0000-0003-0395-1752"
13
- affiliation: "Kronos Fusion Energy"