From 8814158296718bbbbc5caeceee27d264388ec05e Mon Sep 17 00:00:00 2001 From: Bryce Lovell <40742705+BryceWDesign@users.noreply.github.com> Date: Sun, 23 Aug 2026 08:09:51 -0700 Subject: [PATCH] Add SFR-5 Reality Gradient inverse-design framework --- CHANGELOG.md | 10 + CITATION.cff | 2 +- FINAL_STATUS.md | 49 ++- MANIFEST.sha256 | 83 +++-- PROOF_OF_CONCEPT.md | 22 +- README.md | 46 ++- VALIDATION_REPORT.md | 36 +- VERSION | 2 +- check_stellarforge.py | 83 ++++- configs/reactor/sfr5_reality_gradient_a.json | 107 ++++++ docs/16_SOURCE_REUSE_MAP.md | 16 + docs/17_REFERENCES.md | 4 + docs/19_RESEARCH_ROADMAP.md | 36 +- docs/20_RESULTS_LEDGER.md | 13 + docs/reactor/11_WHERE_WE_ARE.md | 17 +- docs/reactor/30_SFR5_REALITY_GRADIENT.md | 47 +++ docs/reactor/31_SFR5_PROMOTION_GATES.md | 28 ++ external_solvers/README.md | 4 + ...sfr5_inverse_design_evidence_contract.json | 49 +++ ...REALITY_GRADIENT_TECHNICAL_BASIS_2026.json | 58 ++++ pyproject.toml | 2 +- results/README.md | 20 +- .../sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md | 27 ++ .../sfr5/sfr5_reality_gradient_a_v0100.json | 299 +++++++++++++++++ sbom.spdx.json | 10 +- .../reactor/sfr5_reality_gradient.schema.json | 61 ++++ scripts/generate_release.py | 3 +- scripts/run_sfr5_reality_gradient.py | 41 +++ src/ix_stellaratorforge/__init__.py | 6 + .../architecture_search.py | 121 +++++++ src/ix_stellaratorforge/reality_gradient.py | 305 +++++++++++++++++ .../sfr5_inverse_design.py | 315 ++++++++++++++++++ .../reactor/test_sfr4_integrated_campaign.py | 9 +- tests/reactor/test_sfr5_reality_gradient.py | 157 +++++++++ 34 files changed, 1948 insertions(+), 140 deletions(-) create mode 100644 configs/reactor/sfr5_reality_gradient_a.json create mode 100644 docs/reactor/30_SFR5_REALITY_GRADIENT.md create mode 100644 docs/reactor/31_SFR5_PROMOTION_GATES.md create mode 100644 external_solvers/sfr5_inverse_design_evidence_contract.json create mode 100644 provenance/SFR5_REALITY_GRADIENT_TECHNICAL_BASIS_2026.json create mode 100644 results/sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md create mode 100644 results/sfr5/sfr5_reality_gradient_a_v0100.json create mode 100644 schemas/reactor/sfr5_reality_gradient.schema.json create mode 100644 scripts/run_sfr5_reality_gradient.py create mode 100644 src/ix_stellaratorforge/architecture_search.py create mode 100644 src/ix_stellaratorforge/reality_gradient.py create mode 100644 src/ix_stellaratorforge/sfr5_inverse_design.py create mode 100644 tests/reactor/test_sfr5_reality_gradient.py diff --git a/CHANGELOG.md b/CHANGELOG.md index ac0d9fd..dce5178 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.10.0 — 2026-08-22 — Reality Gradient and Adaptive Inverse Design + +- Added SFR-5 Reality Gradient as a fail-closed architecture-search layer above the preserved SFR-4 evidence. +- Derived the magnetic autopsy directly from committed v0.9 result/config artifacts: 80 candidates, zero combined topology passes, 3.8265x transform gap to the minimum gate, 3.887% normalized excursion slack, and a held-out normal-field error 12.9825x above its limit. +- Added explicit independent evidence lanes so the direct-filament topology result and held-out reconstruction result cannot be merged into a fictitious physical coilset. +- Added normalized augmented-Lagrangian-style constraint pressure while deliberately withholding any backward geometry gradient until a real movable-geometry evaluator supplies sensitivities. +- Added rejected-family memory, architecture-stagnation logic, movable plasma/winding-surface/coil degrees of freedom, and a production-solver promotion contract. +- Added SFR-5 config/schema, deterministic runner, persisted result, provenance, documentation, external evidence contract, release checks and tests. +- Preserved zero earned fusion-progress credit and all high-authority equilibrium, confinement, TBR, net-electric, magnet, safety and hardware gates as open. + ## 0.9.0 — 2026-08-22 — Integrated Physical Promotion and Heat Exhaust - Attempted all seven requested workstreams in one fail-closed campaign: physical coils, finite-beta equilibrium, coil/plasma co-design, particle confinement, burn, magnet engineering and reactor systems. diff --git a/CITATION.cff b/CITATION.cff index bf687f1..b555e87 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,7 +1,7 @@ cff-version: 1.2.0 message: "If you cite IX-StellaratorForge, cite this repository and state the evaluated release/version and evidence authority." title: "IX-StellaratorForge: Evidence-Driven Stellarator Fusion Reactor Reference Design Framework" -version: "0.9.0" +version: "0.10.0" date-released: 2026-08-22 authors: - family-names: "Lovell" diff --git a/FINAL_STATUS.md b/FINAL_STATUS.md index 9a91354..3e6a27e 100644 --- a/FINAL_STATUS.md +++ b/FINAL_STATUS.md @@ -1,46 +1,39 @@ -# IX-StellaratorForge v0.9.0: Integrated Physical Promotion and Heat Exhaust +# IX-StellaratorForge v0.10.0: Reality Gradient and Adaptive Inverse Design ## Bottom line -All seven requested computational workstreams were attempted. The executable reduced campaign completed, but the result is not a fusion promotion. +The v0.9 SFR-4 integrated campaign remains preserved: its declared nominal and steady heat envelope passes the reduced screen, while its scanned physical coil family fails with zero combined topology passes across 80 direct-filament cases. -The heat architecture passes its declared nominal and steady screening envelope. The scanned physical coil family fails. +Version 0.10.0 adds SFR-5 Reality Gradient and converts that failure into a governed architecture-search decision rather than increasing brute-force sampling of the same magnetic representation. -Top-level verdict: +Top-level SFR-5 verdict: -`INTEGRATED_REDUCED_CAMPAIGN_COMPLETE__NOMINAL_HEAT_ENVELOPE_SCREEN_PASS__PHYSICAL_COIL_EQUILIBRIUM_CONFINEMENT_AND_FUSION_UNPROVEN` +`REALITY_GRADIENT_AUTOPSY_COMPLETE__CURRENT_MAGNETIC_FAMILY_REJECTED__ADAPTIVE_INVERSE_DESIGN_PATH_DEFINED__NO_PHYSICS_PROMOTION` -## What passed +## Executed SFR-5 diagnosis -The selected heat architecture separates distributed first-wall heat, concentrated divertor exhaust and blanket neutron heat. At the declared 1 GW fusion target and Q=20 ledger: +SFR-5 regenerates its values from the committed SFR-4 result and configuration: -* first-wall peak heat flux: approximately 0.294 MW/m2; -* divertor peak heat flux: approximately 5.724 MW/m2; -* nominal first-wall tungsten surface: approximately 401.2 C; -* first-wall surface at the declared 1 MW/m2 steady upper bound: approximately 523.8 C; -* divertor tungsten surface: approximately 678.3 C; -* divertor water flow: approximately 426.0 kg/s through 960 parallel channels; -* mean channel velocity: approximately 7.56 m/s; and -* hydraulic pumping screen: approximately 0.122 MW. +* SFR-4 direct-filament candidates: 80; +* combined topology passes: 0; +* transform factor required merely to reach the minimum iota gate: approximately 3.8265x; +* remaining normalized radial-excursion slack in that same topology lane: approximately 3.887%; and +* separate held-out richer-basis RMS normal-field error: approximately 12.9825x its declared limit. -The selected requirements are a helium-cooled segmented-W/graded-W-RAFM/ODS-RAFM first wall, isolated PbLi DCLL blanket, and a separately bounded water-cooled W/OFHC-Cu/CuCrZr divertor. The water and PbLi systems never share a boundary, penetration or heat exchanger. +The direct-filament topology and held-out reconstruction are preserved as separate evidence lanes. They are not combined into a fictitious physical coilset. -This resolves the nominal and declared steady heat allocation only at reduced-model authority. Stable detachment, the 3-D island footprint, critical heat flux, boiling stability, erosion, cyclic fatigue, irradiation, disruptions, accidents and hardware qualification remain unproven. +## What changed -## What failed +The fixed helical plus fixed hybrid filament-basis family is rejected as the preferred target for more brute-force sampling. SFR-5 opens plasma-boundary, winding-surface, nonplanar-coil, current-group and engineering keep-out degrees of freedom for the replacement search. -Eighty direct-filament Biot-Savart coil configurations were executed. Zero pass both the transform and radial-excursion gates. The best declared scoring case reaches approximately 0.0653 mean iota against a minimum 0.25 requirement. The richer held-out normal-field reconstruction is approximately 6.49% RMS against a 0.5% screen. +The base release computes normalized constraint pressure but deliberately does not fabricate a geometry gradient. Real geometry sensitivities, constrained winding-surface optimization, discrete nonplanar coils, single-stage finite-beta co-design, particle/transport evidence, 3-D neutronics, magnet qualification, integrated plant analysis and hardware remain `NOT_RUN`. -The classical scanned helical family is rejected. Increasing its current did not solve the missing transform without violating other field-quality requirements. +## Preserved v0.9 heat result -## What could not run +The selected separated first-wall/blanket/divertor architecture still passes its declared nominal and steady reduced heat envelope. That remains requirement-level evidence only; stable detachment, 3-D island footprints, transient heat, lifetime, critical heat flux, irradiation, structural qualification and accidents remain open. -DESC, VMEC++, SIMSOPT, OpenMC, kinetic transport, CAD, CFD and structural FEA are unavailable in this runtime. The DESC, VMEC++ and OpenMC adapters were explicitly invoked and stopped with exit code 1. The dependency-installation route was attempted and blocked by runtime network policy. No surrogate output was relabeled as production evidence. +## Scientific boundary -## Remaining scientific result +Earned improvement toward demonstrated equilibrium, confinement, ignition, TBR, net-electric power, qualified magnets, safety or hardware remains exactly **0.00%**. -The 3.5 MeV alpha gyroradius scale is approximately 0.0449 m at 6 T, but no alpha retention is credited. The Q=20 design-iota burn requirement, including the declared alpha-deposition and bremsstrahlung assumptions, requires approximately H_ISS04 2.00. That target cannot be assigned to the failed physical coil family. - -Earned improvement toward demonstrated confinement, ignition or fusion remains exactly **0.00%**. - -The useful advance is narrower and real: the repository now has an executable heat-exhaust requirement and a stronger rejection of an inadequate magnet family. The next design action is a fundamentally different nonplanar modular-coil optimization, not another increase in current through the rejected helices. +The useful v0.10 advance is a stronger research-control result: failed magnetic evidence now determines which representation must change next, while the software is prohibited from promoting that decision into a physical fusion claim. diff --git a/MANIFEST.sha256 b/MANIFEST.sha256 index 809c43b..3073e6e 100644 --- a/MANIFEST.sha256 +++ b/MANIFEST.sha256 @@ -14,11 +14,21 @@ b2925494121094b26d47c1eae3c1c2a2f9e892df44be6db2d882c9b616a9e4fc BOM/SFR3_FIELD 48f4c9d3354daa0b3cd6cca529883a2fcf01c9ea2fbdfe4863f0cdf8af236758 BOM/SFR4_INTEGRATED_PROMOTION_BOM.csv eb551aec75bf47e755ac5c6b47cd56e9f305cd2298b9e31b7549d51b269cda54 BOM/SFR4_INTEGRATED_PROMOTION_BOM.md ae5773e56d167372bf7c37ea10191efdf280735f4e0508d5d3f675468bd0e64a BOM/SOFTWARE_BOM.md -0367a8a8a698403d8c8a0b652d5638824cb2a40efcb67047dbfa624268f06835 CHANGELOG.md +dbf15fbc35c6f8e9ead879c03f0e46d38380e39885d2b809d05c421dc1a92368 CHANGELOG.md +2c4f19f51f82bc1b030b96a7c81cd6042039ffa98c9a250895009e988c657e52 CITATION.cff +7e6cb85d12c63615de11c5ad447a7d2ee67966c4ebc22a503ca751f8e029aebb CONTRIBUTING.md +ab351564b9f7c3cfd093aea2a32d81186fffa5dda7f18abc6fbf8150af3545c1 FINAL_STATUS.md +a1910a705ab6b4f879c4129e6cd40191c44f7c1574f7528371648eec1f7f9ddf LICENSE +1db51de28df66287ac49a6a8be7e3102d23faefea5b6e55319a374756112970b LICENSING.md +596893249c69f9267165cb132a8dd7f2a79f20c0629d7b038db7d87048fd2bbe NOTICE +ccfa19892b2ec67ab807522a6cf6c4f52f88c1ae6382181ccd8139f56f13de35 PROOF_OF_CONCEPT.md +833807f32bfda5d776a6dbfe95a85db5115c48a250f2b98dc8af0d3129944ede README.md +4d4c473db189c494b0ef89bb4b4719dd1f0a6fd1baf9c30885cd7050a22f16af SECURITY.md +455336d4b14f5add863c527ebf23f7ddf57326ae1ce64da8ef8e5b167c325d9f VALIDATION_REPORT.md +dc24feb5bd35084d8ae32a4eafbec12352707d4662401fcbcc9bbd696cde77a9 VERSION c92c87524f4e6f0cebcdeb8efb9d1530c3e225e0a50c1e0fd0fce73f599fb452 check_green.py -e0e60e54b8f3a610d03cfb39898e2f1856bc06167fc6ca879cc71ee75aa2a3e7 check_stellarforge.py +602a27f5a53c6adb95ea815949344667d27a2fa1bc7df808670d0012278f81e9 check_stellarforge.py b9b7a02ec0d6df702cae96e023e7da06b7ca4a2707c8397d2d5440a3c7ca9f1a check_vnext.py -46e9662133144005d128e4f7ab581f1b54a51cb5c217353f1a9bbec3f4cf909c CITATION.cff 213134f9aa49df59e33925b17391fa2d08e64d2463b40eff388ffb3d6083196a configs/baselines/axisymmetric_negative_control.json 1fe77095b374819712f56ba69d5c52cce28de36048977c8a415b8e4918bd8e8f configs/baselines/matched_helical_5fp.json 4f77d1d8b61ce241f7448db70653549c1920e27ab4fd75e38a5d5d9118bc6251 configs/candidates/c6_seed.json @@ -31,13 +41,13 @@ ac37ec451b99f55bd05723ac70eaa3bd40738dd75f4f2818efb39780bbecd8db configs/reacto bb0170cde1b77598d8abe50d97f48bbebebd89985c04fb22e6cf432f7a061611 configs/reactor/sfr3_dual_boundary_ahis_a.json 81a94227137cdd9cb6d01ba3b97ec143ac2bf836cabcb84d597bd2d4fecc13ba configs/reactor/sfr3_field_integrity_shell_a.json 789d8fb6c9004fe35de2ff891fca0ece6226323811aaf4983815635199768129 configs/reactor/sfr4_integrated_physical_promotion_a.json +942e90bb71d2bdb561618c0a764d2ab965e0e18b3de5b60b935e3b81d628cf85 configs/reactor/sfr5_reality_gradient_a.json fa82e05e890f650da2c292d10ab25052a9ad680b83da8d2baef7d8b5edae5d71 configs/system/claim_gates.json 32521732a38a98c6bbadb75121238b9792e369e5c5b8ee731e81c64dd27df520 configs/system/engineering_screen.json db8b3af721d463adf1b80ac0d12a0cd2da8d6da67b9a4517af5db95d6cb94711 configs/system/geometry_error_monte_carlo.json f500e3b35709497bbc9517b364c10c75e1a49ce79c7c71e01c82c232c7bf7913 configs/system/rf_robustness.json b3e790eec9fa6d9ebe3eb1bf3c7e938998389e9764e506314cba8b34b3ba1332 configs/vnext/seed_league.json d38f4a1b9fb60e742bca3e8e2c868ca9139d795787c0d2473afab958258c6a72 configs/vnext/solver_promotion.json -7e6cb85d12c63615de11c5ad447a7d2ee67966c4ebc22a503ca751f8e029aebb CONTRIBUTING.md bf71afb7c583842aecfd368bd50c33e751ba06e82f35d98f0f5f4eaf59c145b8 docs/00_PROJECT_CHARTER.md e05bbef95aedf349c4d3919bc53086cb701c6e8624e6e66642223bf8818874fc docs/01_RESEARCH_QUESTION.md ee2661c222934ac69a32b2fba714cbf18423f3eb52105bf9a25572286c1f76b6 docs/02_CLAIM_BOUNDARY.md @@ -54,12 +64,15 @@ da2970b5bfe825585c4f535382f8341598e8e38658d11aacee07698262f33e4a docs/12_MODEL_ 77d4495a2e6f2bfdefd350c2968bf1a07553834c2caf0175088c7db2bcb219d5 docs/13_KILL_CRITERIA.md ed565c19b881f46ad624be5399acda5c3d4d8b731da7608d2a86461b998ecf72 docs/14_RISK_REGISTER.md 6d3d14b86230a0aa4eca32e037ec501de952570eabc687371865f8796f1d3614 docs/15_EXTERNAL_SOLVERS.md -376f3b9ccf8c9fcf00a4fb61daedae81350c078cbd6d31a87c50e2c469037a49 docs/16_SOURCE_REUSE_MAP.md -a1280c042573e3a358fe76155953ccc1bb84c99787db5be0808232532efc9327 docs/17_REFERENCES.md +f650fa6c3d32cb011c7e50e73caf4ac1ac5670bbf9a0e63a605f8720754e0cc6 docs/16_SOURCE_REUSE_MAP.md +883e1434a688c37c3ae88675f1006db55d091cf0ff63cd8da5c65584306bf05c docs/17_REFERENCES.md 1a15bb4d5a73f54661817ac1fd3c56b019d04d0aa09d7132ab14834ee5283c02 docs/18_REVIEWER_GUIDE.md -d6f140c6e3429ffd828d9b66cb4c85b4565c1c74c343b24ff004521144f2e3e6 docs/19_RESEARCH_ROADMAP.md -96b114e56d7cfe6fb61fae3f03b049db100f2b084249c49ba92f2b1dbc439d51 docs/20_RESULTS_LEDGER.md +8d4ad3547571658e9934b5f3ca9fcc34547892cd8b3bb824d1db881599895acc docs/19_RESEARCH_ROADMAP.md +56db17db9c5406a2e62dda4c8e276d9fbf8e3886992505f8b26f9aafe98faa39 docs/20_RESULTS_LEDGER.md 4343a11317ba89108a21e6e83a439e9292fac89e45f2be6e6eb07142e2cb7c07 docs/21_PHYSICAL_BUILD_BOUNDARY.md +cdb25693a496f1dff331d9b6e2cf39f23ed34d97c314b748334431261ab8e8c8 docs/IX_FUSION_FOUNDATION_CHANGELOG.md +9a676d87c0311d942fe5cdf17004ecfa2cd192d6d2b9d231c162a6dc58300b35 docs/IX_FUSION_FOUNDATION_LICENSE.md +c7380070b54fc2d138c0336b63338a6e2758660fdcbf06fb77d45fb6c74e23c8 docs/IX_FUSION_FOUNDATION_README.md bbf883e8431908a9ffc1addb0998412a50f531466c38c80bff1219213d850d62 docs/closure/00_CLOSURE_CAMPAIGN.md eeac8499a492b0d19391294cc9be724479a8f83246662056389b0a428dce7cf4 docs/closure/01_GATE_STATUS.md 05647698ff45f33189eb9c4ca96bbed862ac390614d780f5b02c048957f8a996 docs/closure/02_EXTERNAL_EXECUTION_PLAN.md @@ -67,9 +80,6 @@ eeac8499a492b0d19391294cc9be724479a8f83246662056389b0a428dce7cf4 docs/closure/0 7c05c4867784406b80b5ee9e3b56df0d650d338784e436371641a546bfa2e5a7 docs/closure/05_EXTERNAL_SOLVER_EXECUTION_PACK.md df2e955c0c0fc5db0abf13a1f8173aa2200bae1a9cb909a4ab65c4379003637f docs/closure/06_MAXIMUM_COMPUTATIONAL_CLOSURE.md 92185e1df235caef209b25bddd0d2a4d1d3500fc25f60ac516eb44e36b16d93f docs/closure/07_PRODUCTION_SOLVER_HANDOFF.md -cdb25693a496f1dff331d9b6e2cf39f23ed34d97c314b748334431261ab8e8c8 docs/IX_FUSION_FOUNDATION_CHANGELOG.md -9a676d87c0311d942fe5cdf17004ecfa2cd192d6d2b9d231c162a6dc58300b35 docs/IX_FUSION_FOUNDATION_LICENSE.md -c7380070b54fc2d138c0336b63338a6e2758660fdcbf06fb77d45fb6c74e23c8 docs/IX_FUSION_FOUNDATION_README.md 743a85b834a2e95a79ea291ab3592c33ccd6e2ded3c878a18eb2358e59b8f512 docs/reactor/00_SFR1_REVA_REFERENCE_DESIGN.md 9bcd288b34c636c0fbcd7b5dd6c9e349086dfb995f527a001c884bbdab517178 docs/reactor/01_PARAMETER_AUTHORITY.md 29574244508ccd22e667e4214a8684695621c4e0cc389c11f53260d5a7a271fc docs/reactor/02_CORE_AND_MAGNET_ARCHITECTURE.md @@ -81,7 +91,7 @@ e20b20f263bfa036d2a321b20d3870957f4e912da40fa12a6af6417382e5b405 docs/reactor/0 f9d6ed65bf4e5d00b6d60cb40a210a39871e874ebf3668d4f4d3bdce5bba0c90 docs/reactor/08_SAFETY_AND_ASSURANCE.md 6b1bfa02b8e3f6f3a1d358c8a24460b344b5622613a6b593fc2ff7b858387968 docs/reactor/09_2026_TECHNICAL_BASIS.md ce85fc253360439ab35bd2e0a9356568247ac6c623bb93a07fe004626d5067cd docs/reactor/10_DEVELOPMENT_GATES.md -82fb9a89d0800f0eccab8531a42d0dd1bf16b526587746e16ac2ca0f9c228c2e docs/reactor/11_WHERE_WE_ARE.md +5e0ad6ac9c11df7c7da37d6614468ae38cc07e7bce7109567933f0fe9e53ab42 docs/reactor/11_WHERE_WE_ARE.md b036ca47f9aacc78a7704ee87fc26444e0b18039c8992cf73f09f44597aad5cc docs/reactor/12_SFR2_DYNAMIC_COMPRESSION.md 3c5a8c268b41a6ef6dfab45fba532b2b5595645f85974e1d324b7b46a773e40b docs/reactor/13_SFR2_PROMOTION_GATES.md 4e45cab33a9bc997c399717a53fccd79af459085cf3b784c0691892f2369aa86 docs/reactor/14_SFR2_PHASE_PROGRAMMED_BREATHING.md @@ -100,6 +110,8 @@ dc4f17547ee78062e37ec0c257f3ea28a227257ed1028ff79c0157a9e0e84b73 docs/reactor/2 70b2079fcf9ca47e6e6de940fe9283b68336d2940686d69755062331369390cc docs/reactor/27_SFR4_SOLVER_ATTEMPTS.md 579140824242a81e5b2545e3edb23f723ae412e44011a0520ee1de1aab6f4053 docs/reactor/28_SFR4_PROMOTION_GATES.md 3d4b0ac7a4c58bb236694d1869dd8edf05d430503ff73296a8d514dfe7c6a409 docs/reactor/29_SFR4_DECISION.md +f46d5a2568b4b75733b70ee6998620f5fc1130723d544d3966e9d159c39bebd5 docs/reactor/30_SFR5_REALITY_GRADIENT.md +da7f6483f427ffb9ecd936ea4d3ba23a39fd747372f7883e3ffca2ab4cef7e98 docs/reactor/31_SFR5_PROMOTION_GATES.md 3c951d70f8daa038da5d8f266ca5ffe5bffc1e7fd5313e975e86ea226b06cf2e docs/vnext/00_VNEXT_SCIENTIFIC_THESIS.md 5c604754dab8694b0e10b7c6396592067db933d3c9b9432a65c36d98788fb2e3 docs/vnext/01_MULTI_FIDELITY_PROTOCOL.md a16a5af059a9ff1460d8fde2ec78602cb388f104df170ef3a68def16dfebcee0 docs/vnext/02_REPO_REUSE_LEDGER.md @@ -110,6 +122,7 @@ fb9fe442da0ac01abc1912e84159a1c98f2212569baf2e7c1b6ab1d7d0657510 docs/vnext/05_ cf13e57d707fabd7920f1e8f2b93bed2fd44065ea26b786d15f04aa67ae87fb6 docs/vnext/07_EXECUTION_SEQUENCE.md a35dc295de1a418dffc271be79a5afaa32ee2606154a4215cb078740a97a3e35 docs/vnext/08_KILL_CRITERIA_VNEXT.md 8f9bce8d213b0e87af1a66da1bdb9df558b679edcced743d5b771efd683f6200 examples/README.md +755143c524fa91301a448a9cdd92ed88e20dc68351bfaf6e9cc2de0f1c7c60cb external_solvers/README.md a16658f773480fe395f0f4d8424a33cec60a19b16049d32c7449cf0a2d0f3a9d external_solvers/adapters/analyze_openmc_3d_tbr.py f5eb4aa9bfd1f93775bc19afd81f1a0f40e0d63b02d14d0e80c73d63b901b9d7 external_solvers/adapters/build_openmc_axisymmetric_proxy.py 6c4a78259a45722d211b3e619abae5ff17f52ec0ab5a32d7148f7df6b50f7c94 external_solvers/adapters/run_desc_equilibrium.py @@ -122,17 +135,12 @@ ff148fe0522b7f7e9ab661adb08e7645e69746abbc8b85cb6e090a9c9d260a95 external_solve d8a9bb730e97de9f8eef651c2f972dc81653c160f6276758776166c9c4947078 external_solvers/inputs/input.SFR1_QA_2FP_REF 445ade74d49212ae8d5c00a52b3f77703c5bcc4dc3183ea9c1afc2d654daa7c4 external_solvers/inputs/input.SFR1_QI_3FP a2e09c625aed1dc6ffc47d91508389c21ae435810a27f22a7cb2e9db52a0df91 external_solvers/inputs/input.SFR1_QI_PWO_4FP -becb02d85585127e584c0bad5c4ab91bab35dc4812bfeae4fe1b60611a6db4a3 external_solvers/README.md f654adf4a7ea4c42e13fba20ebf0109220f1b897dd9e0a5fa87e91b1106dda69 external_solvers/requirements-high-fidelity.txt 8927e3e7ea0a235b097c857df78dc99b9a096bfa5c125d85f4945cd17584c239 external_solvers/result_contract.schema.json 608e08deb9ded6b5fd14518562c712275d6d58b9dee770f292c4036656af992f external_solvers/sfr3_dual_boundary_evidence_contract.json 5b2d6ffab34985d14a37fb6e70d67194a817ab78a921a8e8b1f33d08d2d2ec03 external_solvers/sfr3_field_integrity_evidence_contract.json 9e5999cad412929eae9d18a5391ce34085f9ba9596dc0951c0f15d3880f92838 external_solvers/sfr4_integrated_evidence_contract.json -2a28e6d9246027dc68b8c401b86634d9e60edc3d3229d018572db4d895eaad3d FINAL_STATUS.md -a1910a705ab6b4f879c4129e6cd40191c44f7c1574f7528371648eec1f7f9ddf LICENSE -1db51de28df66287ac49a6a8be7e3102d23faefea5b6e55319a374756112970b LICENSING.md -596893249c69f9267165cb132a8dd7f2a79f20c0629d7b038db7d87048fd2bbe NOTICE -a9e468ad27083404995557f4a8809b302f77753797e7a4229afd9dcfc66168cc PROOF_OF_CONCEPT.md +8ae9f859850efbdfac1ec3d708ecc1ef027602d046e11c52fda0e9bd27808e98 external_solvers/sfr5_inverse_design_evidence_contract.json fed86927a74e9d833acabbe7817d737aa3f8fcc6d8f377ae71dfa04eb9e38d57 provenance/EXTERNAL_TECHNICAL_BASIS_2026.json 45b2990ea886b5da071b7d0c1f2a71ff1970b82b586afa3a915a78835e8eb74c provenance/ORIGIN_INPUTS.json cc595590d7df524ba3e4598fe38144d266bed0cf2964b520533db61f01043016 provenance/SFR2_ACTUATION_TECHNICAL_BASIS_2026.json @@ -140,36 +148,36 @@ cc595590d7df524ba3e4598fe38144d266bed0cf2964b520533db61f01043016 provenance/SFR f7a865cb6659f48f91049f1f64ef98f18ba986a6534959a446b7f30d1f6196d0 provenance/SFR3_DUAL_BOUNDARY_TECHNICAL_BASIS_2026.json 78f0e9c5d85d401a85a7794b8782736918b07bdcd2d07f698e3076f8a54d8d81 provenance/SFR3_FIELD_INTEGRITY_TECHNICAL_BASIS_2026.json 8c4500555af1a84c9b2d16c437c4a06a3c672eb8130e67a7cbdfa6066dcb4ef9 provenance/SFR4_INTEGRATED_TECHNICAL_BASIS_2026.json -2c39b34797cfe3ecf5ce4bbbbb6b0b93a62ad51b840ec2375b6220449f7304cf pyproject.toml -e3fb50283f22e6c01ab825972d2de3fb29f8ce7d6d2f7fe94e2a97c1cfbfcb20 README.md -f89b4f5a1f0df6dcee5017ed3ba0dbdd582c26a70f1ae411512c32c403f25f15 results/ablations/c6_ablations.json +c0982f8928cab7bbb2263d706e73631af1b64a09a171aa957adc9ac4311e4145 provenance/SFR5_REALITY_GRADIENT_TECHNICAL_BASIS_2026.json +aa97a3bf73c7566f005c964dbf2c9cbc1d3a425e083d3dca7a60b0755b540f44 pyproject.toml +7959c33ee833fe3b5324bc2f7d7d8ee476a66c7e84a41238dbeb0e562a88097e results/README.md ef99833f1d6127e24cc360ea040d1c525a9a83dce643a4a7ef0ae55e8276159f results/ablations/README.md +f89b4f5a1f0df6dcee5017ed3ba0dbdd582c26a70f1ae411512c32c403f25f15 results/ablations/c6_ablations.json 91dfeac7a439599da4382c7bbd1585d75bf63c024716f0696cdd2de5b00114df results/baselines/matched_helical_5fp.json 89cab72f4dc070f6f993922e34881843fae15bfd34b918339948b758fc1e3d89 results/closure/sfr1_v020_closure_campaign.json 16f35ed0499a91b1236419172f4222939e555e6ef88e74e8163a4f5e5954d514 results/closure/sfr1_v030_closure_campaign.json -d30d6098d366b94c6304acb972e9a055c1d5e9d41c3c04f037bd43025f2efa86 results/computational_closure/sfr1_v040.json 00f8597c0ff2571a888c7cca08fd3c510c321924bdb64870919a0fc3ccb27f76 results/computational_closure/SFR1_V040_RESULT.md +d30d6098d366b94c6304acb972e9a055c1d5e9d41c3c04f037bd43025f2efa86 results/computational_closure/sfr1_v040.json 258d82bf7295127b6e8f2989f0dadea3c63c2436393d0e31b4c828e2ec2c5b3f results/evidence/IXFUSION-POC-001.json -4bf569ceeba36987c5c3750e7a0931b578fc6b568fdfd6bf841ce87a7dac91cc results/evidence/loss_ledger.json 71c531a8f2c324194c78cf7a641b5e09a5ea676622fbb3ba4f2035e98724c0a0 results/evidence/README.md +4bf569ceeba36987c5c3750e7a0931b578fc6b568fdfd6bf841ce87a7dac91cc results/evidence/loss_ledger.json +e79039efa867015c3af2c43ba1aac3f513617d8cc891ed022abb8b3565f32964 results/figures/README.md 75c50557949d11ca6c7a326b42550a3e907604a88d9a465d8a0e61c811d168a5 results/figures/baseline_poincare.png ee608be45721fe325dd855e3ef65dba6f183aa63d6976a70f76d35b95d6f6e59 results/figures/c6_poincare.png 85f9435aace8942c3346238d844480a4cc0bc9f7a797756c8d7eda61db5578b8 results/figures/poc_metric_comparison.png -e79039efa867015c3af2c43ba1aac3f513617d8cc891ed022abb8b3565f32964 results/figures/README.md cb71de5e29502699b22486ac41b8edc7c0f898fbc6a31b0288cb452d3c922cbb results/figures/rf_robustness.png -b05ec26e1a89eaa29144ea945509585c79e5275c3edd53d04568407d146b8ae0 results/monte_carlo/geometry_error_robustness.json b93ba3547db751236de862c18b7d186553ac824ed97c32d7eae72d854a0f4689 results/monte_carlo/README.md +b05ec26e1a89eaa29144ea945509585c79e5275c3edd53d04568407d146b8ae0 results/monte_carlo/geometry_error_robustness.json 404968254bb7179d206888f348ebae74e4e4ec3b2321231bf19095709a32775b results/monte_carlo/rf_robustness.json -1d0f535108846efc2cf82e87dac8140383c76491d50c04fe6ecf8d9a05a29aff results/poc/c6_candidate.json 6fdffc2bd36c0fdf2d3c9935f5da66dea69d76bc8862f10da260fc8f90549805 results/poc/POC_RESULT.md +1d0f535108846efc2cf82e87dac8140383c76491d50c04fe6ecf8d9a05a29aff results/poc/c6_candidate.json 8f90c172de8d0be2bc788b3eb054901a0f703e4487399f307047ed3a6b66b26a results/poc/verdict.json fb9d8c91204c9cc6947d71b094fede656c053c6faa14ef4294082c4e7b9f2da3 results/reactor/sfr1_rev_a_readiness.json -93d08ac321363b34425c26cb5ad076c7c664d1924e1a5793ff8575c6aea2997a results/README.md 732c2fd5a8f2e86f6b2c75ab4b038331a4b4902b7ae6ff98ee8741e6d95031a3 results/sfr1_poc/SFR1_POC_RESULT.md 2f1ad48d4d8aef052bcd61436f622180b013a9364436a640e1944121ae41db0b results/sfr1_poc/sfr1_poc_v030.json 9b0b22934caa8626c900027a340b6f7c65f116bd8ca0c18ba8478799da5ce8d2 results/sfr1_poc/sfr1_poc_v040.json -09f0c08c630702d17d89c0ba99c8585d24c8b25c7ab3f7b3d33d629d5d91ea35 results/sfr2/sfr2_rev_a_screen_v050.json 5d40a8d343023a48a5c5c8d89e9194447d86a8d4c83ca76507eae492251a5193 results/sfr2/SFR2_REVA_SCREEN_RESULT.md +09f0c08c630702d17d89c0ba99c8585d24c8b25c7ab3f7b3d33d629d5d91ea35 results/sfr2/sfr2_rev_a_screen_v050.json 13ce8a27fe47d32d29c66e405adb78eaa0760129281f25772abbd36d34dfcebf results/sfr2_actuation/SFR2_ACTUATION_OVERLAY_A_RESULT.md ecf8b8c18779ed9e9c8b82bbc86cb1989fbd16d283b65b0f8c2ecf132dfec5dc results/sfr2_actuation/sfr2_actuation_overlay_a_v060.json 020d0157fe920b1b5e17d43229c4ddf8ee85d3258f3eba3db293e33683c057a1 results/sfr3_dual_boundary/SFR3_DUAL_BOUNDARY_AHIS_A_RESULT.md @@ -178,10 +186,12 @@ ecf8b8c18779ed9e9c8b82bbc86cb1989fbd16d283b65b0f8c2ecf132dfec5dc results/sfr2_a 396673ad083c45a5fd79d40c447f158d2d3021821e8abac024a5171756b6d69b results/sfr3_field_integrity/sfr3_field_integrity_shell_a_v070.json b8f300c8dbab375a66b39cc4812ed30bdbab4f0c6d70f114f1b79452a9e796ad results/sfr4_integrated/SFR4_INTEGRATED_PHYSICAL_PROMOTION_A_RESULT.md 42aa9e0de1b2f332ec12ee426a2cc87231f92ff7d7dc148a2e1b0db0b6b139fb results/sfr4_integrated/sfr4_integrated_physical_promotion_a_v090.json +61a10759114268595759f1514b18789abdd2e6276f1e7ce22456fb84a16407c2 results/sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md +ecd8996c7edc005efaaccf1a72656f0d8e360f94eb144ab5ceb41786f915b871 results/sfr5/sfr5_reality_gradient_a_v0100.json ef748a2605b4ad18f1c7e584f950eba589b23713840178e87bb6a99d676912ef results/vnext/CURRENT_VERDICT.md 3ad823aeaa19e17a12dae6cc89aaa08be9274ee0fa9139624ff784d50293ccfd results/vnext/readiness_report.json 999d106c2531098142befeb8d0d91be43dc7138e8e76706accaee1cb9275049f results/vnext/robust_nfp_sweep.json -b6c7286093c2e16ffd831a3b47c3e37add8c50992b836ea93d9453b7ab5ef47e sbom.spdx.json +9a7b9fd7d766c4979c3cbf4980f4b6e06eeef7adf07c0ae8753920ddc04db8c5 sbom.spdx.json 7c9fabaeb4203bfda860216209ee88dd37394f8ae9924d2e2212181987bcb2cd schemas/candidate_config.schema.json c6d5fbeae5928227c542e363c0c23e77fdb27c9bd0920e2157ad3c9f6edccbd1 schemas/evidence_bundle.schema.json 005aa089d6ff4625b1711409e69fd0930e51c77cdb25f411d285959489d70094 schemas/external_solver_run.schema.json @@ -191,7 +201,8 @@ c6d5fbeae5928227c542e363c0c23e77fdb27c9bd0920e2157ad3c9f6edccbd1 schemas/eviden 3537095fab27007c60817f7ce99bc9bcd5c6961518b77bb9e512bfe4fb4fa00a schemas/reactor/sfr3_dual_boundary_ahis.schema.json 937b74da6e2d7b9ece5750229098632e05876d88991c49390c23ddcb7ad58a6c schemas/reactor/sfr3_field_integrity_shell.schema.json 6bfc1a14dd79fb0eb697c457e1ca1c0246ccd4d32e6b7bc1c9e180e31b6ab0c9 schemas/reactor/sfr4_integrated_physical_promotion.schema.json -55998b388a2ab0fa8ec901c9254e2cc950e6f30566ab2d2b6608366f7de36ff3 scripts/generate_release.py +58dd01644d7a225c254321507631887ae4748b2ea7b3300ccde5b52b769d813c schemas/reactor/sfr5_reality_gradient.schema.json +40882e870b9a382a0175b1c2d1812abb71a24f0970ccfc33aaaacc17d6a3af34 scripts/generate_release.py 93d41bc1427215972a9f063c2634d7e64b4b6f3e949bf2fc606d62e58261db50 scripts/generate_v040_evidence.py 239034ac6eb9cdeacae2d7426c3f39902829cf555bad0700c9e63076bd96cdde scripts/make_manifest.py 10246a789d6d78d33903a35c3faa7794f02ac489f3d8477401d40a3cfbb22a04 scripts/report_closure_status.py @@ -208,9 +219,9 @@ aa8287248608a082e5389b375b7788d5623b79811dc7312db32cc7d23c4c5e3e scripts/run_sf f32430b199feeb5589e2a5e774b2b57c7e038f99202e9c704aa1173c3df2fbc0 scripts/run_sfr3_dual_boundary.py 0ebf5aaf25ba5df3c0d0e55f8fc70c05cef5c734fc34bdfc7ab0bd0e69d41b86 scripts/run_sfr3_field_integrity.py e62c301900a715fc1f13833d8dd219b6519bb191829c10a6bfb849220aa6e4df scripts/run_sfr4_integrated_campaign.py +417672a7af9f78a2bc3564f1e89cef3868b31aac5a41d3eea9e1cbc5bba0e46f scripts/run_sfr5_reality_gradient.py 1d9e4c599e2576456c630baa2a87c692ac293bc2adf3594018c59faf56059151 scripts/run_zero_arg_tests.py c2c7f4a139c8c4554e185367124f9f3c18a9e2f32f4853a7bdf14c313c3657db scripts/verify_manifest.py -4d4c473db189c494b0ef89bb4b4719dd1f0a6fd1baf9c30885cd7050a22f16af SECURITY.md 6028d8212cdc131f025a4384a82316f80a3b87efba75279cc94d72f862bb39ff src/ix_fusion/__init__.py 935a1c1166b0c1ea35a82256345000bf2c73ded718d77773bc27a71ecce28f7d src/ix_fusion/__main__.py 7def5e3e431fc8d5908c9d54fe1cd4c95d6dd4ca12b05cc6d1ac867c22cd7038 src/ix_fusion/ablations.py @@ -246,8 +257,9 @@ fb5ab38d90a59ce276069e36c51618a696375d1378b1bf93cb00cb82970855d3 src/ix_fusion/ 79942b9c36b822df8d5f689ba3c37bcc4aa84ecac96acf921050d452f01a117c src/ix_fusion/vnext/protocol.py dfbe4b75e868c32d7080da8d5cf1c6ef88bb7920360a91edf424f593be3e4acb src/ix_fusion/vnext/seed_league.py 4877068052ed8f357ece164da0668e23a1dd21ae9e5e2e62aebde2ffe6bbee67 src/ix_fusion/vnext/solver_registry.py -71cd52332535065dd3bc7bd05483b404a2003363f835b9bc1d7b91243fd02b70 src/ix_stellaratorforge/__init__.py +31867510772af4465492bd527615719422d42d3054a57771b733523765510f04 src/ix_stellaratorforge/__init__.py 935a1c1166b0c1ea35a82256345000bf2c73ded718d77773bc27a71ecce28f7d src/ix_stellaratorforge/__main__.py +8fc742eef2bb1abc6f7fda9d00ef5c1d5b71095614dcd31f1de1a7e46c423e99 src/ix_stellaratorforge/architecture_search.py 6b68c441fd7f404a9f0152ca2c903b000057dd500041db666451a687d1059881 src/ix_stellaratorforge/burn.py 63e02d3487c8541e2de6a7e7ed532d6f7ff7a3fd6e5d25488edd1f3392b393a8 src/ix_stellaratorforge/cli.py 87837dfe172b5e72e2453214e46ffe9edd9cf78d05bcbb91a69c187f31dc5b28 src/ix_stellaratorforge/closure.py @@ -264,11 +276,13 @@ ccfe1d85a8ce307e13a0dd6741f9641021249f8c3281e36e7266a3972b9cce58 src/ix_stellar 1cc27b9880eb49986e8ade1e68b4dc8c1c4c3137ac9b1f2fb60660d00444d806 src/ix_stellaratorforge/poc.py d6026ef7fe67d9c18a6081f76624b13d7b4a2d7bf7ff55f7fd4dfc1c5a0ed18f src/ix_stellaratorforge/reactor.py 82e9f82e97472fc3bb75355983cb129b246f9518d13a2810038d58ba6f536bf4 src/ix_stellaratorforge/readiness.py +6f26503ff3764af4a74f0f0464b943dc567b87d66439d7d5a79ea885bc8ee2be src/ix_stellaratorforge/reality_gradient.py af8f3a1d5831c10a754eb6f8b095df5daa889ea49bb12e9768ffbfa52b7dcfa8 src/ix_stellaratorforge/sfr2.py b67877f03e5006bb440525e33aeb718fa4e9c6afbc4e7ad8ec542207c233e54a src/ix_stellaratorforge/sfr2_actuation.py f46fd4cef387895948ed38f5e13aa630c35f119d9c8851610e48b1ad63e8d77e src/ix_stellaratorforge/sfr3_dual_boundary.py c739b16fbe3958ffea1b981bae84ee01e0ea5ccfb24e0e9b4e131905126633c6 src/ix_stellaratorforge/sfr3_field_integrity.py 515939cddc545c80fdd3e9b60ac4446429285059d090f78cccf1b96a13340d1a src/ix_stellaratorforge/sfr4_integrated_campaign.py +73fc3320cdbd01e9527cecedfcca829231bfec4063ef713e432c1049e3e3b203 src/ix_stellaratorforge/sfr5_inverse_design.py f021654d07a36fba883764fbd2ec1b27da8baeb777fd464df2bc63569dd32175 src/ix_stellaratorforge/vacuum_codesign.py b9d7d3cb22cb7c62071bea73ecb717fe58d32b77dbbd32446203138cd69de13c tests/conftest.py 2c2e7bce5dbc7c8f3833eee47c7dfe2770589497ce2485780ffc830e2eaecee8 tests/reactor/test_closure_campaign.py @@ -280,7 +294,8 @@ d5fd653c55b9ef6f7da31e96c436cd7dfabab9e721c34e725f7d506bbed262df tests/reactor/ 33a06af86683842b3aa2d8b410ce922aabdd12f8673709a7e1f2546c812c5291 tests/reactor/test_sfr2_rev_a.py 3d754d8657cdf8344cb9d62e4cc79b3189af8f60683c51ea397023ede8a964db tests/reactor/test_sfr3_dual_boundary.py 86d88c3140180f74e207e9c71045bb10a0fb2e6db95d2c8e30158be71f65ccaf tests/reactor/test_sfr3_field_integrity.py -e0febca8adfa00fb62b481f8cb9dea982ffbb29f796d1cdd70f644120292cb8f tests/reactor/test_sfr4_integrated_campaign.py +bf5b0af180dd662a808dd27ea16b896b7884eaa627c6153b1a6469ca67eb29ef tests/reactor/test_sfr4_integrated_campaign.py +791c02a47e8a6c6e8f1877b443145702cd1f6cec154780192f81a475c830d9b4 tests/reactor/test_sfr5_reality_gradient.py 4896b20fd7778a2397d7904dc69b5e32e52669126899d30b821822d4ccc5b879 tests/reactor/test_v040_external_adapters.py 1fce6d8873f9c88d7ec18a83c912e6e044e61c06a3bb57e5f3251d712b7e677c tests/reactor/test_v040_maximum_closure.py e100edacbd2c12d8344eeb2fc931cb9f7e12feb20efb4b3c507966eb047275a3 tests/test_config.py @@ -298,5 +313,3 @@ e6a7cb3065c409f277472594b4d226d6f66d535ef1eee83735774f0b93527b97 tests/test_sen 512cbbeaf5d5552ae1f24d165bb47642ec4736dfe5c6ac66943d7b7801bed7d6 tests/test_solver_contracts.py 9640683b5d434d15c9919affc1139f4c8c7531074abf7423783f0ce656b7429f tests/test_tracing.py f947aa90adebb206ee0b8c7a3a124aa959c3525eec4accecabbd0a2aaf1b1810 tests/vnext/test_vnext_protocol.py -f76300a3ff23e047bd60c6078d06ae125273d3f3214989d4341c6f2e5cdc5125 VALIDATION_REPORT.md -9d8c94f1ad3ea96b1e2ac4914fda4cb93c76b4a3e0d8cc6dd8976d6c0b227d15 VERSION diff --git a/PROOF_OF_CONCEPT.md b/PROOF_OF_CONCEPT.md index dc9d2e3..5c21c34 100644 --- a/PROOF_OF_CONCEPT.md +++ b/PROOF_OF_CONCEPT.md @@ -1,6 +1,14 @@ # IX-StellaratorForge — executable evidence overview -Release: **0.9.0** +Release: **0.10.0** + +## SFR-5 Reality Gradient and adaptive inverse design + +v0.10.0 converts the preserved SFR-4 magnetic rejection into a deterministic architecture-search decision. It derives the diagnostic values from the committed SFR-4 JSON and config, preserves the topology and held-out reconstruction as separate evidence lanes, and stores the rejected family in fail-closed memory. + +Result: `REALITY_GRADIENT_AUTOPSY_COMPLETE__CURRENT_MAGNETIC_FAMILY_REJECTED__ADAPTIVE_INVERSE_DESIGN_PATH_DEFINED__NO_PHYSICS_PROMOTION`. + +The result means the fixed helical plus fixed hybrid filament-basis family is no longer the preferred target for more brute-force sampling. It does not prove a replacement coilset. Geometry sensitivities, winding-surface optimization, discrete nonplanar coils, finite-beta co-design, transport, TBR, magnet qualification, plant closure and hardware all remain unrun. ## SFR-4 integrated campaign @@ -68,6 +76,7 @@ python scripts/run_sfr2_actuation_overlay.py python scripts/run_sfr3_field_integrity.py python scripts/run_sfr3_dual_boundary.py python scripts/run_sfr4_integrated_campaign.py +python scripts/run_sfr5_reality_gradient.py python check_stellarforge.py ``` @@ -114,6 +123,17 @@ Tracked SFR-4 outputs: - `docs/reactor/28_SFR4_PROMOTION_GATES.md` - `docs/reactor/29_SFR4_DECISION.md` +Tracked SFR-5 outputs: + +- `configs/reactor/sfr5_reality_gradient_a.json` +- `results/sfr5/sfr5_reality_gradient_a_v0100.json` +- `results/sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md` +- `schemas/reactor/sfr5_reality_gradient.schema.json` +- `provenance/SFR5_REALITY_GRADIENT_TECHNICAL_BASIS_2026.json` +- `external_solvers/sfr5_inverse_design_evidence_contract.json` +- `docs/reactor/30_SFR5_REALITY_GRADIENT.md` +- `docs/reactor/31_SFR5_PROMOTION_GATES.md` + ## Promotion boundary A low-authority model may reject a candidate. It may not declare one successful. diff --git a/README.md b/README.md index c8003f1..9f266cc 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ **Evidence-driven stellarator fusion reactor design and computational co-design program.** -IX-StellaratorForge preserves the original `IX-Fusion` research lineage and builds a reactor-level evidence program above it. **SFR-1 Rev A** remains the steady-state reference architecture; **SFR-2 Rev A** remains a separate dynamic-compression assumption breaker; **SFR-3 Field Integrity Shell A** remains the synthetic magnetic-error-control branch; **Dual Boundary AHIS A** remains the independently monitored engineering boundary. Version 0.9.0 adds **SFR-4 Integrated Physical-Promotion Campaign A**, which attempts physical coil fields, equilibrium, co-design, particle confinement, burn, magnet engineering, heat exhaust and reactor systems without promoting unavailable production evidence. +IX-StellaratorForge preserves the original `IX-Fusion` research lineage and builds a reactor-level evidence program above it. **SFR-1 Rev A** remains the steady-state reference architecture; **SFR-2 Rev A** remains a separate dynamic-compression assumption breaker; **SFR-3 Field Integrity Shell A** remains the synthetic magnetic-error-control branch; **Dual Boundary AHIS A** remains the independently monitored engineering boundary; **SFR-4 Integrated Physical-Promotion Campaign A** remains the integrated heat/magnetic campaign. Version 0.10.0 adds **SFR-5 Reality Gradient and Adaptive Inverse Design A**, which converts the SFR-4 magnetic rejection into a fail-closed architecture-search program instead of increasing brute-force sampling of the same family. -> **Release:** `0.9.0: Integrated Physical Promotion and Heat Exhaust` +> **Release:** `0.10.0: Reality Gradient and Adaptive Inverse Design` > -> **Repository verdict:** `GREEN` when all preserved evidence and the SFR-4 integrated reduced campaign reproduce. +> **Repository verdict:** `GREEN` when all preserved evidence, the SFR-4 integrated campaign, and the SFR-5 adaptive inverse-design autopsy reproduce. > > **SFR-2 primary verdict:** `NO_PRIMARY_CASE_CROSSES_OPTIMISTIC_IGNITION_PROXY` > @@ -18,8 +18,37 @@ IX-StellaratorForge preserves the original `IX-Fusion` research lineage and buil > > **SFR-4 verdict:** `INTEGRATED_REDUCED_CAMPAIGN_COMPLETE__NOMINAL_HEAT_ENVELOPE_SCREEN_PASS__PHYSICAL_COIL_EQUILIBRIUM_CONFINEMENT_AND_FUSION_UNPROVEN` > +> **SFR-5 verdict:** `REALITY_GRADIENT_AUTOPSY_COMPLETE__CURRENT_MAGNETIC_FAMILY_REJECTED__ADAPTIVE_INVERSE_DESIGN_PATH_DEFINED__NO_PHYSICS_PROMOTION` +> > No branch claims demonstrated confinement, ignition, net energy, tritium self-sufficiency, net electricity, buildable hardware, reactor safety, or reactor feasibility. +## What v0.10.0 adds + +SFR-5 treats the `0 / 80` SFR-4 magnetic result as information about the search representation, not an invitation to sample the same family more densely. Its diagnosis is regenerated from the committed SFR-4 result and thresholds rather than hard-coded into a new narrative. + +| SFR-5 diagnostic | Executed result | +|---|---:| +| SFR-4 direct-filament candidates | 80 | +| Combined topology passes | 0 | +| Mean-transform factor required to reach the minimum iota gate | 3.8265x | +| Remaining normalized excursion slack | 3.887% | +| Held-out richer-basis RMS normal-field error / declared limit | 12.9825x | +| Earned fusion-progress credit | 0 | + +The two magnetic diagnostics remain separate evidence lanes because they are not the same physical coil representation. SFR-5 rejects continued brute-force search of the fixed helical plus fixed hybrid filament basis as the preferred next move, while explicitly **not** rejecting stellarators, quasi-isodynamic configurations, nonplanar modular coils or fusion. + +The new inverse-design contract allows the plasma boundary, winding surface, nonplanar coil geometry, current groups, REBCO orientation and engineering keep-outs to move. Constraint failures become normalized pressure signals. A backward geometry gradient is only permitted when a real solver supplies analytic, automatic-differentiation or controlled finite-difference sensitivities; the base release deliberately records that step as `NOT_RUN`. + +Primary v0.10 artifacts: + +- `results/sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md` +- `results/sfr5/sfr5_reality_gradient_a_v0100.json` +- `configs/reactor/sfr5_reality_gradient_a.json` +- `docs/reactor/30_SFR5_REALITY_GRADIENT.md` +- `docs/reactor/31_SFR5_PROMOTION_GATES.md` +- `external_solvers/sfr5_inverse_design_evidence_contract.json` +- `provenance/SFR5_REALITY_GRADIENT_TECHNICAL_BASIS_2026.json` + ## What v0.9.0 adds All seven requested computational workstreams were attempted. The result is deliberately split: the heat architecture passes its declared nominal and steady reduced envelope, while the scanned physical coil family fails. @@ -202,6 +231,7 @@ python scripts/run_sfr2_actuation_overlay.py python scripts/run_sfr3_field_integrity.py python scripts/run_sfr3_dual_boundary.py python scripts/run_sfr4_integrated_campaign.py +python scripts/run_sfr5_reality_gradient.py python check_stellarforge.py ``` @@ -238,7 +268,7 @@ No core is privileged: 2FP QA reference, 3FP QI, 4FP QI/piecewise-omnigenous, 6F “Full” means complete at the system-architecture inventory level. It is **not** falsely labeled a procurement/fabrication BOM: final quantities, nuclear compositions/enrichment, conductor sizing/current, pressure ratings, safety setpoints, vendors, part numbers and drawings remain solver/hardware dependent. -## Evidence gates after v0.9 +## Evidence gates after v0.10 1. **G1 equilibrium — production execution open.** Inputs are complete; real finite-beta DESC and VMEC++ convergence/cross-code evidence has not been executed in this build runtime. 2. **G2 coils — new architectures executed, no promoted set.** Low/intermediate tests reject current fixed boundary/coil combinations; true plasma/coil co-optimization, REBCO Ic/strain over winding packs, loads/support FEA, tolerances and quench remain open. @@ -259,13 +289,15 @@ Dual Boundary AHIS A is also independently gated. Only its configuration and red SFR-4 is independently gated. Its specification passes; its scanned coil family fails; its nominal and declared steady reduced heat screen passes. CAD-linked nonplanar coil optimization, DESC/VMEC++ equilibrium, islands/stability, alpha and thermal transport, 3-D edge/divertor physics, CFD/FEA/fatigue/irradiation, OpenMC TBR, integrated burn/plant analysis and hardware remain `NOT_RUN`. +SFR-5 is independently gated. Only `SFR5_G0_SPEC_AND_AUTOPSY` is `PASS_REDUCED`: the v0.9 magnetic evidence is reinterpreted as an architecture-family rejection and a declared inverse-design search direction. Movable-geometry sensitivities, winding-surface feasibility, discrete nonplanar-coil realization, single-stage finite-beta plasma/coil co-design, transport, 3-D heat/magnet/neutronics closure, integrated plant analysis and hardware remain `NOT_RUN`. Constraint pressure is diagnostic until a real movable-geometry evaluator supplies sensitivities; SFR-5 assigns zero unearned physics or fusion credit. + ## Quality gate ```bash python check_stellarforge.py ``` -`IX-STELLARATORFORGE: GREEN` means release integrity, 114 tests, preserved SFR-1/SFR-2/SFR-3 evidence, the dual-boundary reduced screen, the SFR-4 integrated campaign, BOM contracts, license, tracked computations and solver contracts reproduce. **It never means fusion was achieved.** +`IX-STELLARATORFORGE: GREEN` means release integrity, the complete deterministic test suite, preserved SFR-1/SFR-2/SFR-3 evidence, the dual-boundary reduced screen, the SFR-4 integrated campaign, the SFR-5 Reality Gradient autopsy, BOM contracts, license, tracked computations and solver contracts reproduce. **It never means fusion was achieved.** ## License and permission contact @@ -279,6 +311,10 @@ A LinkedIn connection, message, discussion, download, citation or repository acc - `FINAL_STATUS.md` - `PROOF_OF_CONCEPT.md` +- `docs/reactor/30_SFR5_REALITY_GRADIENT.md` +- `docs/reactor/31_SFR5_PROMOTION_GATES.md` +- `results/sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md` +- `results/sfr5/sfr5_reality_gradient_a_v0100.json` - `docs/reactor/25_SFR4_INTEGRATED_PHYSICAL_CAMPAIGN.md` - `docs/reactor/26_SFR4_HEAT_EXHAUST_RESOLUTION.md` - `docs/reactor/27_SFR4_SOLVER_ATTEMPTS.md` diff --git a/VALIDATION_REPORT.md b/VALIDATION_REPORT.md index bbfd45f..cb4564f 100644 --- a/VALIDATION_REPORT.md +++ b/VALIDATION_REPORT.md @@ -1,33 +1,31 @@ # IX-StellaratorForge Validation Report -Release: **0.9.0** +Release: **0.10.0** Date: **2026-08-22** -Authority: **software integrity plus mixed low/intermediate analytical and direct-filament screening** +Authority: **software integrity plus preserved low/intermediate analytical/direct-filament evidence and a fail-closed adaptive inverse-design autopsy** -## v0.9 validation scope +## v0.10 validation scope -The SFR-4 focused suite adds eleven tests covering the seven-workstream specification, 80-case physical coil rejection, production-solver fail-closed behavior, alpha gyroradius boundaries, burn-loss bookkeeping, heat partition, first-wall and divertor temperatures, hydraulic requirements, heat sensitivity, magnet nonqualification, conditional reactor bookkeeping and exact persisted-result reproduction. +The complete suite contains **122 deterministic pytest tests**. Eight SFR-5 tests cover config fail-closed behavior, dynamic derivation of the SFR-4 magnetic autopsy, independent evidence lanes, rejected-family memory, zero unearned physics credit, nonfabrication of geometry gradients, finite-difference/constraint-pressure primitives, architecture-stagnation decisions and exact persisted-result reproduction. -One additional release-contract test checks the 64-row SFR-4 BOM. The complete suite contains **114 deterministic tests** when combined with the preserved 102-test v0.8 release. +The preserved SFR-4 reproduction test was also hardened so optional package discovery is treated as runtime metadata rather than scientific evidence. Installing an unrelated optional package such as CAD tooling can no longer invalidate the deterministic campaign core. -## Executed evidence +## Executed SFR-5 evidence -* 80 direct-filament Biot-Savart and vacuum field-line cases; -* one held-out 120-filament normal-field reconstruction at the selected field-period count; -* 3.5 MeV alpha gyroradius scope; -* Bosch-Hale D-T burn and ISS04 Q=20 requirement with bremsstrahlung; -* 16-point radiation-fraction and divertor-area heat sensitivity matrix; -* multilayer first-wall and divertor 1-D conduction; -* distributed-water-loop mass flow, velocity, pressure drop and pump power; -* REBCO centerline geometry, magnetic-pressure and stored-energy scopes; -* exact D-T neutron and tritium source ledger; -* breeding-coverage constraint; and -* conditional plant arithmetic. +* exact reuse of the committed v0.9 SFR-4 result and declared magnetic thresholds; +* 80-candidate / zero-combined-pass source invariant; +* 3.8265x mean-transform factor to the minimum iota gate; +* 3.887% normalized excursion slack in the same topology lane; +* 12.9825x held-out RMS normal-field excess in a separate reconstruction lane; +* normalized augmented-Lagrangian-style constraint pressure; +* cryptographically fingerprinted rejected-family memory; +* explicit movable plasma-boundary, winding-surface, nonplanar-coil and current degrees of freedom; and +* fail-closed G1-G8 external evidence gates. ## Negative and open evidence -No physical coil passes. DESC, VMEC++, SIMSOPT and OpenMC are unavailable. Particle confinement, finite-beta equilibrium, transport, stable detachment, thermal transients, structural survival, full 3-D TBR, sustained burn, net electricity, safety and hardware remain unpromoted. +No replacement physical coilset is produced in the base release. Geometry sensitivities, QUADCOIL/SIMSOPT-class optimization, finite-beta equilibrium, particle confinement, neoclassical/turbulent transport, stable detachment, thermal transients, structural survival, full 3-D TBR, sustained burn, net electricity, magnet qualification, safety and hardware remain unpromoted. ## GREEN meaning -GREEN means the repository, configuration, persisted reduced result, tests, BOMs, manifests and fail-closed boundaries reproduce. It does not mean the heat solution is physically qualified or that fusion performance improved. +GREEN means the repository, configuration, persisted reduced results, 122 tests, manifests, release metadata and fail-closed evidence boundaries reproduce. It does not mean fusion was achieved or that SFR-5 has discovered a physically viable replacement magnet architecture. diff --git a/VERSION b/VERSION index ac39a10..78bc1ab 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.0 +0.10.0 diff --git a/check_stellarforge.py b/check_stellarforge.py index 73cc21a..bf1ff95 100644 --- a/check_stellarforge.py +++ b/check_stellarforge.py @@ -31,6 +31,11 @@ run_integrated_campaign, validate_integrated_config, ) +from ix_stellaratorforge.sfr5_inverse_design import ( + PASS_VERDICT as SFR5_VERDICT, + run_sfr5_campaign, + validate_sfr5_config, +) CONTACT = "https://www.linkedin.com/in/brycewdesign/" LICENSE_REF = "LicenseRef-IX-StellaratorForge-Eval-Only-1.1" @@ -50,7 +55,7 @@ def run(label: str, command: list[str]) -> bool: def main() -> int: - print("IX-STELLARATORFORGE v0.9.0 QUALITY GATE\n") + print("IX-STELLARATORFORGE v0.10.0 QUALITY GATE\n") failures: list[str] = [] config = load_reactor_config(ROOT / "configs/reactor/sfr1_rev_a.json") @@ -127,6 +132,19 @@ def main() -> int: print(f"{'SFR-4 integrated-campaign invariants':.<52} {'PASS' if sfr4_spec_ok else 'FAIL'}") failures.extend(sfr4_errors) + try: + sfr5_raw = json.loads( + (ROOT / "configs/reactor/sfr5_reality_gradient_a.json").read_text(encoding="utf-8") + ) + sfr5_errors = validate_sfr5_config(sfr5_raw) + sfr5_spec_ok = not sfr5_errors + except Exception as exc: # noqa: BLE001 + sfr5_raw = {} + sfr5_errors = (f"SFR-5 config parse/validation failed: {exc}",) + sfr5_spec_ok = False + print(f"{'SFR-5 Reality Gradient invariants':.<52} {'PASS' if sfr5_spec_ok else 'FAIL'}") + failures.extend(sfr5_errors) + json_files = ( "configs/reactor/parameter_ledger.json", "provenance/EXTERNAL_TECHNICAL_BASIS_2026.json", @@ -159,6 +177,11 @@ def main() -> int: "provenance/SFR4_INTEGRATED_TECHNICAL_BASIS_2026.json", "external_solvers/sfr4_integrated_evidence_contract.json", "results/sfr4_integrated/sfr4_integrated_physical_promotion_a_v090.json", + "configs/reactor/sfr5_reality_gradient_a.json", + "schemas/reactor/sfr5_reality_gradient.schema.json", + "provenance/SFR5_REALITY_GRADIENT_TECHNICAL_BASIS_2026.json", + "external_solvers/sfr5_inverse_design_evidence_contract.json", + "results/sfr5/sfr5_reality_gradient_a_v0100.json", "sbom.spdx.json", ) json_ok = True @@ -176,18 +199,18 @@ def main() -> int: citation = (ROOT / "CITATION.cff").read_text(encoding="utf-8") sbom = json.loads((ROOT / "sbom.spdx.json").read_text(encoding="utf-8")) version_ok = ( - version == "0.9.0" - and 'version = "0.9.0"' in pyproject - and 'version: "0.9.0"' in citation - and sbom["name"] == "IX-StellaratorForge-0.9.0-SBOM" - and sbom["packages"][0]["versionInfo"] == "0.9.0" + version == "0.10.0" + and 'version = "0.10.0"' in pyproject + and 'version: "0.10.0"' in citation + and sbom["name"] == "IX-StellaratorForge-0.10.0-SBOM" + and sbom["packages"][0]["versionInfo"] == "0.10.0" ) except Exception as exc: # noqa: BLE001 version_ok = False failures.append(f"release-version consistency failed: {exc}") - print(f"{'v0.9 release metadata consistency':.<52} {'PASS' if version_ok else 'FAIL'}") + print(f"{'v0.10 release metadata consistency':.<52} {'PASS' if version_ok else 'FAIL'}") if not version_ok: - failures.append("v0.9 release metadata inconsistent") + failures.append("v0.10 release metadata inconsistent") texts = [(ROOT / name).read_text(encoding="utf-8") for name in ("LICENSE", "LICENSING.md", "NOTICE", "README.md")] license_ok = all(CONTACT in text for text in texts) and LICENSE_REF in texts[0] @@ -503,8 +526,12 @@ def main() -> int: systems = persisted_sfr4["workstreams"]["7_reactor_systems"] heat = persisted_sfr4["heat_exhaust_resolution"] promotion = persisted_sfr4["promotion_summary"] + persisted_sfr4_core = dict(persisted_sfr4) + recomputed_sfr4_core = dict(recomputed_sfr4) + persisted_sfr4_core.pop("solver_availability", None) + recomputed_sfr4_core.pop("solver_availability", None) sfr4_screen_ok = ( - persisted_sfr4 == recomputed_sfr4 + persisted_sfr4_core == recomputed_sfr4_core and persisted_sfr4["release"] == "0.9.0" and persisted_sfr4["top_level_verdict"] == SFR4_VERDICT and coil["candidate_count"] == 80 @@ -525,6 +552,41 @@ def main() -> int: if not sfr4_screen_ok: failures.append("SFR-4 campaign stale, overclaimed, or inconsistent") + try: + persisted_sfr5 = json.loads( + (ROOT / "results/sfr5/sfr5_reality_gradient_a_v0100.json").read_text(encoding="utf-8") + ) + recomputed_sfr5 = run_sfr5_campaign(sfr5_raw, persisted_sfr4, sfr4_raw) + diag = persisted_sfr5["magnetic_autopsy"]["diagnostics"] + pressure = persisted_sfr5["constraint_pressure"] + promotion5 = persisted_sfr5["promotion_status"] + sfr5_screen_ok = ( + persisted_sfr5 == recomputed_sfr5 + and persisted_sfr5["release"] == "0.10.0" + and persisted_sfr5["top_level_verdict"] == SFR5_VERDICT + and persisted_sfr5["source_invariants"]["candidate_count"] == 80 + and persisted_sfr5["source_invariants"]["combined_pass_count"] == 0 + and persisted_sfr5["magnetic_autopsy"]["decision"] == "family_switch_required" + and 3.82 < diag["iota_factor_to_minimum_gate"] < 3.84 + and 0.038 < diag["excursion_slack_fraction_of_limit"] < 0.040 + and 12.9 < diag["normal_field_factor_over_limit"] < 13.1 + and pressure["geometry_sensitivity_status"].startswith("NOT_RUN") + and pressure["backward_reality_gradient_status"].startswith("NOT_COMPUTED") + and persisted_sfr5["earned_fusion_progress_credit_fraction"] == 0.0 + and all(value == 0.0 for value in persisted_sfr5["claim_boundary"].values()) + and all( + status == "NOT_RUN" + for gate, status in promotion5.items() + if gate != "SFR5_G0_SPEC_AND_AUTOPSY" + ) + ) + except Exception as exc: # noqa: BLE001 + sfr5_screen_ok = False + failures.append(f"SFR-5 persisted/recomputed campaign failed: {exc}") + print(f"{'SFR-5 Reality Gradient no-overclaim campaign':.<52} {'PASS' if sfr5_screen_ok else 'FAIL'}") + if not sfr5_screen_ok: + failures.append("SFR-5 campaign stale, overclaimed, or inconsistent") + openmc_adapter = (ROOT / "external_solvers/adapters/build_openmc_axisymmetric_proxy.py").read_text(encoding="utf-8") adapters_ok = "NOT the G7 final 3-D stellarator model" in openmc_adapter and "(n,Xt)" in openmc_adapter print(f"{'External solver fail-closed / OpenMC proxy boundary':.<52} {'PASS' if adapters_ok else 'FAIL'}") @@ -538,12 +600,13 @@ def main() -> int: print("-", failure) return 1 print("IX-STELLARATORFORGE: GREEN") - print("Meaning: release integrity, preserved SFR-1/SFR-2/SFR-3 evidence, and the v0.9 integrated campaign reproduce from committed inputs and code.") + print("Meaning: release integrity, preserved SFR-1/SFR-2/SFR-3 evidence, the v0.9 SFR-4 integrated campaign, and the v0.10 SFR-5 adaptive inverse-design autopsy reproduce from committed inputs and code.") print("SFR-2 primary result: no H_ISS04=1 case crosses its optimistic ignition proxy; dynamic compression receives no unmodeled phase/RF or flux-compression credit.") print("SFR-2 actuation result: no declared breathing case improves both cycle-average proxy and fusion power; the tri-lobe translation receives zero unearned fusion credit.") print("SFR-3 result: the synthetic bounded control and fault cases pass their declared thresholds; physical confinement and fusion credit remain zero.") print("Dual-boundary result: reduced thermal and fault-routing screens pass; mechanical plasma-force, wall-lifetime, safety and fusion credit remain zero.") print("SFR-4 result: 80 direct-filament coil cases produce zero topology passes; the declared nominal and steady heat envelope passes, but equilibrium, transport, transient heat, qualified magnets, TBR and fusion remain unproven.") + print("SFR-5 result: the failed magnetic family is rejected as the preferred brute-force search direction; the next search opens plasma boundary, winding surface and nonplanar coil geometry, while real sensitivities and production co-design remain unrun.") print("It does NOT mean finite-beta dynamic MHD, kinetic confinement, qualified high-field magnets, full-3D TBR, ignition, net-electric fusion, safety qualification, or hardware operation has been demonstrated.") return 0 diff --git a/configs/reactor/sfr5_reality_gradient_a.json b/configs/reactor/sfr5_reality_gradient_a.json new file mode 100644 index 0000000..1bb88c0 --- /dev/null +++ b/configs/reactor/sfr5_reality_gradient_a.json @@ -0,0 +1,107 @@ +{ + "schema_version": "0.10.0", + "study_id": "SFR5-REALITY-GRADIENT-A", + "source_release": "0.9.0", + "source_artifacts": { + "sfr4_result": "results/sfr4_integrated/sfr4_integrated_physical_promotion_a_v090.json", + "sfr4_config": "configs/reactor/sfr4_integrated_physical_promotion_a.json" + }, + "constraint_pressure": { + "rho": 2.0, + "normalization": "declared_gate_scale", + "uncertainty_policy": "multiply_active_pressure_by_1_plus_declared_fraction" + }, + "search_policy": { + "stagnation_window": 4, + "minimum_relative_improvement": 0.05, + "forbid_bruteforce_same_family_after_rejection": true, + "candidate_families": [ + "single_stage_nonplanar_modular_fourier_coils_with_movable_plasma_boundary", + "differentiable_winding_surface_proxy_then_filament_realization", + "spatially_constrained_wireframe_or_planar_shaping_array", + "passive_superconductor_hybrid_only_as_secondary_architecture" + ] + }, + "movable_design_variables": [ + { + "group": "plasma_boundary", + "variables": ["R_mn", "Z_mn", "field_period_selection"], + "authority": "optimization_degree_of_freedom_only" + }, + { + "group": "winding_surface", + "variables": ["surface_Fourier_coefficients", "offset_or_clearance_distribution", "maintenance_exclusion_zones"], + "authority": "optimization_degree_of_freedom_only" + }, + { + "group": "coil_geometry", + "variables": ["nonplanar_curve_Fourier_coefficients", "coil_count", "symmetry_class", "placement"], + "authority": "optimization_degree_of_freedom_only" + }, + { + "group": "coil_currents", + "variables": ["independent_current_groups", "current_signs"], + "authority": "optimization_degree_of_freedom_only" + }, + { + "group": "magnet_engineering", + "variables": ["REBCO_winding_orientation", "minimum_coil_spacing", "minimum_coil_plasma_distance", "support_and_access_keepouts"], + "authority": "constraint_only_until_FEA_and_magnet_qualification" + } + ], + "required_external_methods": [ + { + "stage": "winding_surface_feasibility", + "preferred_methods": ["QUADCOIL_or_equivalent_differentiable_winding_surface_optimizer"], + "required_outputs": ["normal_field_error", "curvature_or_complexity_constraints", "force_or_support_proxy", "plasma_and_winding_surface_sensitivities"] + }, + { + "stage": "discrete_nonplanar_coils", + "preferred_methods": ["SIMSOPT_or_equivalent_constrained_filament_optimizer"], + "required_outputs": ["coil_curves", "currents", "quadratic_flux", "length", "curvature", "coil_coil_distance", "coil_plasma_distance"] + }, + { + "stage": "single_stage_codesign", + "preferred_methods": ["SIMSOPT_plus_VMEC_or_DESC_equivalent"], + "required_outputs": ["optimized_plasma_boundary", "optimized_coils", "equilibrium_receipt", "objective_and_constraint_history"] + }, + { + "stage": "physics_promotion", + "preferred_methods": ["DESC", "VMEC++", "Boozer_transform", "guiding_center_orbits", "neoclassical_and_turbulent_transport"], + "required_outputs": ["cross_code_equilibrium", "particle_confinement", "transport_evidence"] + }, + { + "stage": "reactor_promotion", + "preferred_methods": ["OpenMC_DAGMC_or_equivalent", "thermal_CFD", "structural_FEA", "magnet_quench_analysis"], + "required_outputs": ["3D_TBR_and_heating", "heat_exhaust", "structural_margin", "magnet_qualification"] + } + ], + "reopen_conditions": [ + "new_plasma_boundary_family", + "new_winding_surface_parameterization", + "new_nonplanar_coil_parameterization", + "higher_authority_solver_evidence_changes_failure_identity" + ], + "promotion_status": { + "SFR5_G0_SPEC_AND_AUTOPSY": "PASS_REDUCED", + "SFR5_G1_MOVABLE_GEOMETRY_SENSITIVITIES": "NOT_RUN", + "SFR5_G2_WINDING_SURFACE_FEASIBILITY": "NOT_RUN", + "SFR5_G3_DISCRETE_NONPLANAR_COILS": "NOT_RUN", + "SFR5_G4_SINGLE_STAGE_EQUILIBRIUM_CODESIGN": "NOT_RUN", + "SFR5_G5_PARTICLE_AND_TRANSPORT": "NOT_RUN", + "SFR5_G6_HEAT_MAGNET_NEUTRONICS": "NOT_RUN", + "SFR5_G7_INTEGRATED_PLANT": "NOT_RUN", + "SFR5_G8_HARDWARE": "NOT_RUN" + }, + "claim_boundary": { + "fusion_progress_credit_fraction": 0.0, + "production_equilibrium_credit": 0.0, + "particle_confinement_credit": 0.0, + "ignition_credit": 0.0, + "net_electric_credit": 0.0, + "magnet_qualification_credit": 0.0, + "tritium_breeding_credit": 0.0, + "safety_qualification_credit": 0.0, + "hardware_credit": 0.0 + } +} diff --git a/docs/16_SOURCE_REUSE_MAP.md b/docs/16_SOURCE_REUSE_MAP.md index fd23677..3cfaa81 100644 --- a/docs/16_SOURCE_REUSE_MAP.md +++ b/docs/16_SOURCE_REUSE_MAP.md @@ -22,3 +22,19 @@ conceptual provenance, not as evidence that their original application transfers Sacred-geometry and cymatic imagery are retained only as historical design inspiration. Physics terms used in IX-Fusion are symmetry, harmonics, eigenmodes, phase, field periods, and experimentally falsifiable metrics. + +## SFR-5 donor-pattern translation + +SFR-5 additionally audits later IX repositories as software/research-control donors. These are mechanism translations only. + +| Donor | Retained mechanism | Explicitly not transferred | +|---|---|---| +| IX-BlackFox-Cognition | typed evidence/rejection/unknown/quarantine states | model confidence as physical truth | +| IX-BlackFox | fail-closed promotion, receipts, provenance, adversarial review | unrelated operational claims | +| IX-BlackFox-WorldTwin | perturbation scenarios and prediction-versus-result deltas | world-model predictions as fusion evidence | +| IX-Function | bottleneck hypotheses, falsification, negative controls | causal claims without fusion-specific tests | +| IX-IntentRealityLoop | stateful intent/action/reality feedback | automatic promotion from intent to evidence | +| IX-AeroIntegrity / IX-Vahdat | measurement honesty, conservative thresholds, audit discipline | aerospace or unrelated performance claims | +| IX-Sally | selective strict-validation/review patterns only | unfinished or unverified subsystem behavior | + +IX-Shimizu and IX-Trinity are not used in the SFR-5 technical core because no sufficiently grounded mechanism from those repositories was needed for this release. diff --git a/docs/17_REFERENCES.md b/docs/17_REFERENCES.md index 7900d8f..3ae830d 100644 --- a/docs/17_REFERENCES.md +++ b/docs/17_REFERENCES.md @@ -21,6 +21,10 @@ candidate. 9. ITER Organization, Tritium breeding overview. https://www.iter.org/machine/supporting-systems/tritium-breeding +10. SIMSOPT documentation, "Single stage optimization." https://simsopt.readthedocs.io/latest/example_single_stage.html +11. SIMSOPT documentation, "Coil optimization." https://simsopt.readthedocs.io/latest/example_coils.html +12. L. Fu et al., QUADCOIL, differentiable constrained stellarator winding-surface/global coil optimizer. https://github.com/lankef/quadcoil + References are intentionally separated from internal findings. The presence of a technique in the literature does not imply that IX-Fusion has successfully implemented it at the same authority level. diff --git a/docs/19_RESEARCH_ROADMAP.md b/docs/19_RESEARCH_ROADMAP.md index 93b9d6c..a9c5725 100644 --- a/docs/19_RESEARCH_ROADMAP.md +++ b/docs/19_RESEARCH_ROADMAP.md @@ -1,37 +1,31 @@ # Research Roadmap -The next work is not "more exotic geometry." It is higher-authority validation. +The next work is not more brute-force sampling of the rejected magnetic family. It is a higher-authority adaptive inverse-design campaign. -## R1 — Equilibrium +## R1 — Reality Gradient geometry path -Integrate DESC or equivalent. Re-run C6 and matched controls with convergence evidence. -Reject any seed that cannot produce acceptable nested surfaces and transform without -unfair assumptions. +Connect a real movable-geometry evaluator so plasma-boundary, winding-surface and coil variables produce analytic, automatic-differentiation or controlled finite-difference sensitivities. Until this exists, SFR-5 constraint pressure is diagnostic only. -## R2 — Coils and structures +## R2 — Winding-surface feasibility -Use SIMSOPT-class Biot-Savart/coil optimization and incorporate support/strain objectives. -Run field-error Monte Carlo from physical coil perturbations rather than parameter proxies. +Use QUADCOIL or an equivalent constrained differentiable winding-surface/global current solver to test whether candidate plasma boundaries admit engineering-feasible magnetic support. Reject coil-hostile boundaries before expensive discrete-coil optimization. -## R3 — Particle confinement +## R3 — Discrete nonplanar coils and single-stage co-design -Trace guiding-center thermal and fast particles. Replace the internal bounce-action proxy -with orbit-physics metrics from the solved field. +Use SIMSOPT-class optimization to realize nonplanar modular coils with explicit length, curvature, coil-to-coil distance, coil-to-plasma distance, finite-build and robustness objectives. Allow the plasma boundary and coil shapes to move together rather than freezing the target geometry before coil design. -## R4 — Stability and turbulence +## R4 — Equilibrium and confinement -Add finite-pressure equilibrium, MHD stability, and validated turbulent-transport tools. +Run finite-beta DESC and VMEC++/equivalent equilibrium with convergence evidence and independent comparison, then trace guiding-center thermal and fast particles. Replace reduced field-line and bounce-action proxies with orbit and transport metrics from the solved field. -## R5 — Active RF +## R5 — Stability, turbulence and active RF -Use full-wave/deposition modeling to decide whether distributed phase control adds value. +Add MHD stability, validated neoclassical/turbulent transport, and full-wave/deposition modeling. Distributed phase control receives credit only if the solved plasma response earns it. -## R6 — Edge, heat, blanket, cryogenics +## R6 — Edge, heat, magnets and neutronics -Replace normalized penalties with specialist thermal, materials, neutronics, breeding, -magnet, and cryogenic models. +Resolve 3-D edge/divertor physics, thermal/structural lifetime, peak conductor field, REBCO strain/quench, full 3-D neutron transport, shielding and TBR on the same promoted geometry. -## R7 — Plant accounting +## R7 — Plant accounting and hardware -Only after the previous gates, create a complete energy ledger and evaluate whether any -fusion-performance claim is justified. +Only after the preceding gates, construct a complete burn/fuel-cycle/recirculating-power ledger and test representative hardware. Net-electric or reactor-feasibility claims remain closed until those gates are satisfied. diff --git a/docs/20_RESULTS_LEDGER.md b/docs/20_RESULTS_LEDGER.md index 9aecafd..d70c982 100644 --- a/docs/20_RESULTS_LEDGER.md +++ b/docs/20_RESULTS_LEDGER.md @@ -1,5 +1,18 @@ # Results Ledger +## Release 0.10 status + +| Question | Status | Evidence | +|---|---|---| +| Does SFR-5 reproduce the SFR-4 `0 / 80` magnetic rejection from committed evidence? | YES | `results/sfr5/sfr5_reality_gradient_a_v0100.json` | +| Is the minimum-iota gap approximately 3.8265x for the best SFR-4 topology case? | YES | derived from SFR-4 result + declared `0.25` gate | +| Is only about 3.887% normalized excursion slack left in that same topology lane? | YES | same artifacts | +| Is the separate held-out reconstruction about 12.9825x above its RMS normal-field limit? | YES | same artifacts | +| Are those two reduced representations merged into one fictitious coilset? | NO | independent SFR-5 evidence lanes | +| Is the fixed helical/fixed-hybrid family preferred for more brute-force sampling? | NO | family switch required | +| Has SFR-5 produced a viable replacement coilset or finite-beta equilibrium? | NO | G1-G8 remain `NOT_RUN` | +| Did v0.10 earn confinement, ignition, TBR, net-electric, magnet, safety or hardware credit? | NO | all claim-boundary credits remain zero | + ## Release 0.9 status | Question | Status | Evidence | diff --git a/docs/reactor/11_WHERE_WE_ARE.md b/docs/reactor/11_WHERE_WE_ARE.md index e45c584..4e9433c 100644 --- a/docs/reactor/11_WHERE_WE_ARE.md +++ b/docs/reactor/11_WHERE_WE_ARE.md @@ -24,6 +24,18 @@ - Eighty direct-filament coil cases produce zero combined topology passes. The scanned classical helical family is rejected. - The selected separated first-wall, blanket and divertor architecture passes its nominal and declared steady reduced heat envelope. - Production equilibrium, transport, stable detachment, transient heat, qualified magnets, full 3-D TBR and hardware remain unrun. +- Version 0.10 adds SFR-5 Reality Gradient and Adaptive Inverse Design A. +- SFR-5 regenerates the v0.9 magnetic autopsy from committed evidence instead of copying diagnostic numbers into a new claim. +- The fixed helical plus fixed hybrid filament-basis family is stored as rejected for the preferred next search, with explicit evidence required before reopening. +- Plasma-boundary, winding-surface, nonplanar-coil and current degrees of freedom are opened for the next search; no geometry sensitivity or replacement coil result is fabricated in the base release. + +## What v0.10.0 actually found + +The SFR-4 failure contains a representation-level diagnosis. The best helical topology lane would need about 3.8265 times its present mean transform merely to reach the minimum iota gate while retaining only about 3.887% normalized radial-excursion slack. A separate held-out richer basis remains about 12.9825 times above its normal-field RMS limit. + +Because those diagnostics come from different reduced representations, SFR-5 keeps them in independent evidence lanes. Their joint meaning is not that stellarators fail. Their joint meaning is that more brute-force sampling of the same fixed family is a poor next allocation of compute. + +SFR-5 therefore opens the plasma boundary, winding surface, nonplanar coil geometry, current groups and engineering keep-outs as coupled design variables. The base release computes constraint pressure but records geometry sensitivities and the backward Reality Gradient as `NOT_RUN` until a real movable-geometry solver is connected. ## What v0.9.0 actually found @@ -65,13 +77,14 @@ An important correction also emerged: ideal radial compression does not automati ## What this means -The project now contains **four reactor-level research branches plus one integrated engineering layer with different roles**: +The project now contains **four reactor-level research branches plus two integrated design/engineering layers with different roles**: - **SFR-1:** steady-state reference architecture and production-solver path. - **SFR-2:** dynamic/high-field assumption breaker designed to test whether a staggered, strongly transformed, phase-actuated concept earns survival through progressively higher-authority physics. - **SFR-3:** field-integrity overlay designed to preserve a steady stellarator field against error, motion and faults without changing the vessel or inventing material confinement. - **Dual Boundary AHIS A:** engineering-health overlay designed to detect inner-wall, vessel, shield and support problems and coordinate protective actions without touching the plasma or replacing magnetic confinement. - **SFR-4:** integrated promotion and heat-exhaust campaign that rejects the present coil family while retaining a testable steady heat-removal requirement. +- **SFR-5:** adaptive inverse-design layer that converts failed constraints into a governed family-switch/search program and opens coupled plasma/winding-surface/coil degrees of freedom without granting unearned physics credit. No branch or layer has demonstrated ignition, reactor safety or reactor feasibility. @@ -81,7 +94,7 @@ For SFR-3, the decisive next action is **SFR3-G2 physical coil response**: repla For Dual Boundary AHIS A, the decisive next action is a coupled CAD-based thermal, electromagnetic and structural model of the selected geometry, followed by W/RAFM joint coupons, PbLi/coolant compatibility loops, calibrated interspace leak tests and sensor irradiation. The low-authority pass cannot substitute for any of those experiments. -For SFR-4, the decisive next action is a fundamentally different nonplanar modular-coil optimization using a real finite-beta target boundary, followed by DESC and VMEC++ cross-code equilibrium. More current in the rejected classical helices is not a defensible next step. +For SFR-4/SFR-5, the decisive next action is to execute SFR5-G1 through G4: connect a real movable-geometry sensitivity path, run constrained winding-surface feasibility, realize discrete nonplanar modular coils, then perform single-stage coil/plasma optimization against finite-beta equilibrium with independent/cross-code confirmation. More current in the rejected classical helices is not a defensible next step. For SFR-2, the decisive next action remains **SFR2-G1 dynamic equilibrium**: construct a real finite-beta ABAB 3-D equilibrium and determine whether the requested transform survives the proposed actuation/compression cycle without destructive islands, stochastic regions or MHD failure. diff --git a/docs/reactor/30_SFR5_REALITY_GRADIENT.md b/docs/reactor/30_SFR5_REALITY_GRADIENT.md new file mode 100644 index 0000000..dcb5218 --- /dev/null +++ b/docs/reactor/30_SFR5_REALITY_GRADIENT.md @@ -0,0 +1,47 @@ +# SFR-5 Reality Gradient and Adaptive Inverse Design + +## Why SFR-5 exists + +SFR-4 did more than reject one magnetic scan. It exposed a representation bottleneck. + +The best direct-filament helical topology case has mean iota `0.06533346157` against the declared minimum `0.25`, while its normalized maximum radial excursion is already `0.1922252737` against a `0.20` ceiling. Reaching the minimum transform would require about `3.8265x` the present mean transform while only about `3.887%` normalized excursion slack remains. + +A separate held-out richer filament reconstruction has validation RMS `Bn/B = 0.06491274876` against a `0.005` screen, about `12.9825x` the limit. + +Those values belong to different reduced-model lanes. SFR-5 keeps them separate and does not invent a single physical coilset that satisfies or violates all of them simultaneously. + +## The missing control loop + +Earlier releases largely push information forward: + +`plasma target -> magnet family -> reduced physics -> engineering screen -> pass/fail` + +SFR-5 adds the reverse information path: + +`failed constraint -> normalized residual -> constraint pressure -> real sensitivity -> upstream geometry change` + +For a canonical inequality `c_i(x) <= 0`, SFR-5 can maintain non-negative augmented-Lagrangian-style pressure. If a real solver supplies the Jacobian `J = dc/dx`, that pressure can be mapped onto upstream variables through a transpose-Jacobian operation. The base release intentionally stops before this step because no production movable-geometry evaluator is installed. + +No geometry derivative is fabricated from the v0.9 numbers. + +## What is now allowed to move + +The next magnetic search is no longer restricted to current ratios and a fixed helical basis. The SFR-5 contract explicitly opens: + +- plasma-boundary Fourier coefficients and field-period choice; +- winding-surface shape and clearance distribution; +- nonplanar modular-coil Fourier geometry; +- coil count, placement, symmetry class and independent current groups; +- REBCO orientation constraints; +- coil-to-coil and coil-to-plasma spacing; +- support, access and maintenance exclusion zones. + +The primary replacement family is a single-stage nonplanar modular-coil search with a movable plasma boundary. A constrained differentiable winding-surface/global proxy is intended to reject coil-hostile plasma shapes before expensive discrete-coil and equilibrium work. + +## Family rejection memory + +The current `fixed_helical_plus_fixed_hybrid_filament_basis` family is stored as rejected evidence. It may not silently return because a later optimizer prefers it. Reopening requires explicit new evidence such as a different plasma-boundary family, winding-surface parameterization, nonplanar-coil parameterization, or higher-authority evidence that changes the identity of the failure. + +## Claim boundary + +SFR-5 G0 is a reduced architecture autopsy and research-control result. It does not establish a replacement coilset, finite-beta equilibrium, physical confinement, TBR, ignition, net electricity, qualified magnets, safety or hardware operation. Earned fusion-progress credit remains zero. diff --git a/docs/reactor/31_SFR5_PROMOTION_GATES.md b/docs/reactor/31_SFR5_PROMOTION_GATES.md new file mode 100644 index 0000000..a3aa0ec --- /dev/null +++ b/docs/reactor/31_SFR5_PROMOTION_GATES.md @@ -0,0 +1,28 @@ +# SFR-5 Promotion Gates + +SFR-5 is deliberately structured so that a software search decision cannot promote itself into a physics result. + +| Gate | Required evidence | Base v0.10 status | +|---|---|---| +| SFR5-G0 | Reproduce SFR-4 magnetic autopsy, preserve independent evidence lanes, reject brute-force continuation | PASS_REDUCED | +| SFR5-G1 | Movable plasma, winding-surface and coil geometry plus real sensitivities | NOT_RUN | +| SFR5-G2 | Constrained winding-surface/global coil feasibility with normal-field, complexity and force/support limits | NOT_RUN | +| SFR5-G3 | Discrete nonplanar coil curves/currents with spacing, curvature, finite-build follow-up and reproducible receipt | NOT_RUN | +| SFR5-G4 | Single-stage coil/plasma co-design plus finite-beta equilibrium and independent/cross-code confirmation | NOT_RUN | +| SFR5-G5 | Guiding-center/alpha confinement, neoclassical transport and turbulent-transport evidence | NOT_RUN | +| SFR5-G6 | 3-D heat exhaust, magnet forces/strain/quench and full 3-D neutronics/TBR | NOT_RUN | +| SFR5-G7 | Coupled burn, fuel cycle, recirculating power and net-electric plant ledger | NOT_RUN | +| SFR5-G8 | Representative hardware, metrology, electromagnetic/thermal testing, fault and safety evidence | NOT_RUN | + +## Preferred method ladder + +The base release names methods, not results: + +1. QUADCOIL or an equivalent differentiable constrained winding-surface/global proxy; +2. SIMSOPT or an equivalent constrained discrete-filament optimizer; +3. simultaneous plasma-boundary and coil co-design coupled to VMEC/DESC-class equilibrium; +4. particle, neoclassical and turbulent-transport evaluation; +5. 3-D edge/divertor, OpenMC/DAGMC-class neutronics, structural/thermal analysis and HTS qualification; +6. integrated plant and hardware evidence. + +An unavailable tool remains unavailable. A proxy may eliminate a family but may not inherit the authority of a production solver. diff --git a/external_solvers/README.md b/external_solvers/README.md index d74fc51..74845ed 100644 --- a/external_solvers/README.md +++ b/external_solvers/README.md @@ -2,6 +2,10 @@ This directory is an **execution bridge**, not prefilled evidence. +## SFR-5 adaptive inverse design + +`sfr5_inverse_design_evidence_contract.json` defines the fail-closed path from the v0.10 reduced magnetic autopsy to movable-geometry sensitivities, constrained winding-surface feasibility, discrete nonplanar coils, single-stage finite-beta co-design, transport, 3-D heat/magnet/neutronics, plant closure and hardware. The base release names QUADCOIL/SIMSOPT/DESC/VMEC++-class methods as candidate tools but does not claim that any of those production stages ran. + ## SFR-4 integrated campaign `sfr4_integrated_evidence_contract.json` defines nine fail-closed promotion gates spanning physical coils, cross-code equilibrium, stability, particle transport, three-dimensional island-divertor exhaust, thermal/structural qualification, OpenMC neutronics, integrated burn/plant analysis and hardware. v0.9 explicitly attempted the DESC, VMEC++ and OpenMC adapters; all stopped because the production dependencies are absent. diff --git a/external_solvers/sfr5_inverse_design_evidence_contract.json b/external_solvers/sfr5_inverse_design_evidence_contract.json new file mode 100644 index 0000000..de84ddb --- /dev/null +++ b/external_solvers/sfr5_inverse_design_evidence_contract.json @@ -0,0 +1,49 @@ +{ + "contract_version": "0.10.0", + "study_id": "SFR5-REALITY-GRADIENT-A", + "principle": "A reduced SFR-5 autopsy may choose what to test next but cannot promote a replacement magnetic architecture without external solver evidence.", + "gates": [ + { + "id": "SFR5_G1_MOVABLE_GEOMETRY_SENSITIVITIES", + "status": "NOT_RUN", + "required": ["plasma-boundary degrees of freedom", "winding-surface degrees of freedom", "coil degrees of freedom", "constraint Jacobian or controlled sensitivity evidence"] + }, + { + "id": "SFR5_G2_WINDING_SURFACE_FEASIBILITY", + "status": "NOT_RUN", + "required": ["constrained winding-surface/global current solution", "normal-field error", "curvature/complexity limits", "force/support proxy", "reproducible solver receipt"] + }, + { + "id": "SFR5_G3_DISCRETE_NONPLANAR_COILS", + "status": "NOT_RUN", + "required": ["discrete coil curves and currents", "coil-coil distance", "coil-plasma distance", "curvature and length", "normal-field objective", "finite-build follow-up plan"] + }, + { + "id": "SFR5_G4_SINGLE_STAGE_EQUILIBRIUM_CODESIGN", + "status": "NOT_RUN", + "required": ["movable plasma boundary", "finite-beta equilibrium", "coil co-design", "cross-code or independent equilibrium evidence", "constraint history"] + }, + { + "id": "SFR5_G5_PARTICLE_AND_TRANSPORT", + "status": "NOT_RUN", + "required": ["Boozer or equivalent coordinates", "alpha/guiding-center orbits", "neoclassical transport", "turbulent transport evidence"] + }, + { + "id": "SFR5_G6_HEAT_MAGNET_NEUTRONICS", + "status": "NOT_RUN", + "required": ["3-D heat exhaust", "peak conductor field", "structural loads", "REBCO strain and quench", "3-D neutronics and TBR"] + }, + { + "id": "SFR5_G7_INTEGRATED_PLANT", + "status": "NOT_RUN", + "required": ["self-consistent burn/transport coupling", "recirculating power", "gross and net electric ledger", "fuel-cycle closure"] + }, + { + "id": "SFR5_G8_HARDWARE", + "status": "NOT_RUN", + "required": ["representative hardware", "metrology", "thermal-vacuum and electromagnetic testing", "fault and safety evidence"] + } + ], + "automatic_promotion": false, + "missing_evidence_policy": "FAIL_CLOSED" +} diff --git a/provenance/SFR5_REALITY_GRADIENT_TECHNICAL_BASIS_2026.json b/provenance/SFR5_REALITY_GRADIENT_TECHNICAL_BASIS_2026.json new file mode 100644 index 0000000..621d45f --- /dev/null +++ b/provenance/SFR5_REALITY_GRADIENT_TECHNICAL_BASIS_2026.json @@ -0,0 +1,58 @@ +{ + "record_version": "0.10.0", + "study_id": "SFR5-REALITY-GRADIENT-A", + "purpose": "Document the method basis and donor-pattern provenance for adaptive inverse design without transferring unrelated domain claims.", + "internal_donor_translation": [ + { + "source": "IX-BlackFox-Cognition", + "retained": ["typed evidence state", "contradiction and rejection state", "unknown and quarantine discipline"], + "not_transferred": ["domain claims", "model-generated confidence as physical evidence"] + }, + { + "source": "IX-BlackFox", + "retained": ["fail-closed promotion", "receipts and provenance", "adversarial review", "bounded authority"], + "not_transferred": ["unrelated operational assumptions"] + }, + { + "source": "IX-BlackFox-WorldTwin", + "retained": ["perturbation scenarios", "prediction-versus-result deltas", "robustness evaluation"], + "not_transferred": ["world-model claims as fusion evidence"] + }, + { + "source": "IX-Function", + "retained": ["bottleneck hypotheses", "falsification", "negative-control mindset"], + "not_transferred": ["causal claims without fusion-specific evidence"] + }, + { + "source": "IX-IntentRealityLoop", + "retained": ["intent-to-action-to-reality feedback loop", "stateful adaptation after failure"], + "not_transferred": ["automatic promotion of model intent into physical truth"] + }, + { + "source": "IX-AeroIntegrity and IX-Vahdat", + "retained": ["measurement honesty", "conservative thresholds", "auditable evidence handling"], + "not_transferred": ["aerospace or unrelated domain performance"] + } + ], + "external_method_context": [ + { + "source": "SIMSOPT single-stage optimization documentation", + "url": "https://simsopt.readthedocs.io/latest/example_single_stage.html", + "relevance": "Demonstrates simultaneous optimization of plasma-boundary objectives and coil objectives with engineering regularization.", + "credit": "method context only; no SIMSOPT result is claimed by the base SFR-5 release" + }, + { + "source": "SIMSOPT coil optimization documentation", + "url": "https://simsopt.readthedocs.io/latest/example_coils.html", + "relevance": "Documents quadratic-flux, coil-length, spacing, curvature, stochastic-error and finite-build optimization concepts.", + "credit": "method context only" + }, + { + "source": "QUADCOIL", + "url": "https://github.com/lankef/quadcoil", + "relevance": "Differentiable constrained winding-surface/global coil proxy with plasma and winding-surface sensitivities.", + "credit": "method context only; QUADCOIL is not executed in the base SFR-5 release" + } + ], + "nontransfer_rule": "Published methods and donor-repository mechanisms may shape SFR-5 architecture, but no external result, material qualification, confinement result, or hardware performance is assigned to IX-StellaratorForge without candidate-specific execution and evidence." +} diff --git a/pyproject.toml b/pyproject.toml index 8939a2e..51a0afb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "ix-stellaratorforge" -version = "0.9.0" +version = "0.10.0" description = "Evidence-driven stellarator fusion reactor reference-design and co-design framework." readme = "README.md" requires-python = ">=3.11" diff --git a/results/README.md b/results/README.md index c547937..09a9c0b 100644 --- a/results/README.md +++ b/results/README.md @@ -7,16 +7,18 @@ marked as a non-result/unknown. The authoritative regeneration command is: python scripts/generate_release.py ``` -Primary v0.9 review path: +Primary v0.10 review path: -1. `sfr4_integrated/SFR4_INTEGRATED_PHYSICAL_PROMOTION_A_RESULT.md` -2. `sfr4_integrated/sfr4_integrated_physical_promotion_a_v090.json` -3. `sfr3_dual_boundary/SFR3_DUAL_BOUNDARY_AHIS_A_RESULT.md` -4. `sfr3_dual_boundary/sfr3_dual_boundary_ahis_a_v080.json` -5. `sfr3_field_integrity/SFR3_FIELD_INTEGRITY_SHELL_A_RESULT.md` -6. `sfr3_field_integrity/sfr3_field_integrity_shell_a_v070.json` -7. `sfr2_actuation/SFR2_ACTUATION_OVERLAY_A_RESULT.md` -8. `sfr2/SFR2_REVA_SCREEN_RESULT.md` +1. `sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md` +2. `sfr5/sfr5_reality_gradient_a_v0100.json` +3. `sfr4_integrated/SFR4_INTEGRATED_PHYSICAL_PROMOTION_A_RESULT.md` +4. `sfr4_integrated/sfr4_integrated_physical_promotion_a_v090.json` +5. `sfr3_dual_boundary/SFR3_DUAL_BOUNDARY_AHIS_A_RESULT.md` +6. `sfr3_dual_boundary/sfr3_dual_boundary_ahis_a_v080.json` +7. `sfr3_field_integrity/SFR3_FIELD_INTEGRITY_SHELL_A_RESULT.md` +8. `sfr3_field_integrity/sfr3_field_integrity_shell_a_v070.json` +9. `sfr2_actuation/SFR2_ACTUATION_OVERLAY_A_RESULT.md` +10. `sfr2/SFR2_REVA_SCREEN_RESULT.md` Preserved IX-Fusion foundation path: diff --git a/results/sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md b/results/sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md new file mode 100644 index 0000000..eab789b --- /dev/null +++ b/results/sfr5/SFR5_REALITY_GRADIENT_A_RESULT.md @@ -0,0 +1,27 @@ +# SFR-5 Reality Gradient and Adaptive Inverse Design A + +## Executed result + +Top-level verdict: `REALITY_GRADIENT_AUTOPSY_COMPLETE__CURRENT_MAGNETIC_FAMILY_REJECTED__ADAPTIVE_INVERSE_DESIGN_PATH_DEFINED__NO_PHYSICS_PROMOTION` + +SFR-5 derives its diagnosis from the committed v0.9 SFR-4 magnetic result and its declared thresholds. It does not merge the direct-filament topology lane with the independent held-out reconstruction lane. + +- SFR-4 direct-filament cases: **80**. +- Combined topology passes: **0**. +- Transform factor required merely to reach the minimum iota gate: **3.8265x**. +- Remaining normalized excursion slack: **3.887%** of the declared limit. +- Held-out RMS normal-field error relative to its limit: **12.9825x**. + +## Decision + +The present fixed helical plus fixed hybrid filament-basis family is rejected as the preferred next search family. The next program must allow the plasma boundary, winding surface, nonplanar coil geometry, and currents to move together under explicit engineering constraints. + +The primary next family is `single_stage_nonplanar_modular_fourier_coils_with_movable_plasma_boundary`. Winding-surface proxy/global optimization, discrete filament realization, finite-beta equilibrium, particle/transport checks, 3-D neutronics, magnet engineering, and hardware remain promotion gates rather than assumed capabilities. + +## Reality Gradient status + +SFR-5 computes normalized constraint pressure from the existing evidence but deliberately does **not** fabricate a geometry gradient. A backward gradient is only valid after a real movable-geometry evaluator supplies analytic, automatic-differentiation, or controlled finite-difference sensitivities. + +## Claim boundary + +This release does not demonstrate a viable replacement coil set, finite-beta equilibrium, kinetic confinement, TBR, ignition, net-electric power, magnet qualification, safety qualification, or hardware operation. Earned fusion-progress credit remains exactly zero. diff --git a/results/sfr5/sfr5_reality_gradient_a_v0100.json b/results/sfr5/sfr5_reality_gradient_a_v0100.json new file mode 100644 index 0000000..539660c --- /dev/null +++ b/results/sfr5/sfr5_reality_gradient_a_v0100.json @@ -0,0 +1,299 @@ +{ + "claim_boundary": { + "fusion_progress_credit_fraction": 0.0, + "hardware_credit": 0.0, + "ignition_credit": 0.0, + "magnet_qualification_credit": 0.0, + "net_electric_credit": 0.0, + "particle_confinement_credit": 0.0, + "production_equilibrium_credit": 0.0, + "safety_qualification_credit": 0.0, + "tritium_breeding_credit": 0.0 + }, + "constraint_pressure": { + "active_pressure": { + "mean_iota_min": 2.95466461488, + "normalized_max_excursion": 0.0, + "validation_rms_Bn_over_B": 47.930199008 + }, + "backward_reality_gradient_status": "NOT_COMPUTED__NO_FAKE_SENSITIVITY_CREDIT", + "geometry_sensitivity_status": "NOT_RUN__REQUIRES_REAL_MOVABLE_GEOMETRY_EVALUATOR", + "method": "normalized_augmented_lagrangian_pressure_without_fabricated_geometry_gradient", + "multipliers": { + "mean_iota_min": 1.47733230744, + "normalized_max_excursion": 0.0, + "validation_rms_Bn_over_B": 23.965099504 + }, + "rho": 2.0 + }, + "earned_fusion_progress_credit_fraction": 0.0, + "inverse_design_program": { + "candidate_families": [ + "single_stage_nonplanar_modular_fourier_coils_with_movable_plasma_boundary", + "differentiable_winding_surface_proxy_then_filament_realization", + "spatially_constrained_wireframe_or_planar_shaping_array", + "passive_superconductor_hybrid_only_as_secondary_architecture" + ], + "movable_design_variables": [ + { + "authority": "optimization_degree_of_freedom_only", + "group": "plasma_boundary", + "variables": [ + "R_mn", + "Z_mn", + "field_period_selection" + ] + }, + { + "authority": "optimization_degree_of_freedom_only", + "group": "winding_surface", + "variables": [ + "surface_Fourier_coefficients", + "offset_or_clearance_distribution", + "maintenance_exclusion_zones" + ] + }, + { + "authority": "optimization_degree_of_freedom_only", + "group": "coil_geometry", + "variables": [ + "nonplanar_curve_Fourier_coefficients", + "coil_count", + "symmetry_class", + "placement" + ] + }, + { + "authority": "optimization_degree_of_freedom_only", + "group": "coil_currents", + "variables": [ + "independent_current_groups", + "current_signs" + ] + }, + { + "authority": "constraint_only_until_FEA_and_magnet_qualification", + "group": "magnet_engineering", + "variables": [ + "REBCO_winding_orientation", + "minimum_coil_spacing", + "minimum_coil_plasma_distance", + "support_and_access_keepouts" + ] + } + ], + "primary_next_family": "single_stage_nonplanar_modular_fourier_coils_with_movable_plasma_boundary", + "required_external_methods": [ + { + "preferred_methods": [ + "QUADCOIL_or_equivalent_differentiable_winding_surface_optimizer" + ], + "required_outputs": [ + "normal_field_error", + "curvature_or_complexity_constraints", + "force_or_support_proxy", + "plasma_and_winding_surface_sensitivities" + ], + "stage": "winding_surface_feasibility" + }, + { + "preferred_methods": [ + "SIMSOPT_or_equivalent_constrained_filament_optimizer" + ], + "required_outputs": [ + "coil_curves", + "currents", + "quadratic_flux", + "length", + "curvature", + "coil_coil_distance", + "coil_plasma_distance" + ], + "stage": "discrete_nonplanar_coils" + }, + { + "preferred_methods": [ + "SIMSOPT_plus_VMEC_or_DESC_equivalent" + ], + "required_outputs": [ + "optimized_plasma_boundary", + "optimized_coils", + "equilibrium_receipt", + "objective_and_constraint_history" + ], + "stage": "single_stage_codesign" + }, + { + "preferred_methods": [ + "DESC", + "VMEC++", + "Boozer_transform", + "guiding_center_orbits", + "neoclassical_and_turbulent_transport" + ], + "required_outputs": [ + "cross_code_equilibrium", + "particle_confinement", + "transport_evidence" + ], + "stage": "physics_promotion" + }, + { + "preferred_methods": [ + "OpenMC_DAGMC_or_equivalent", + "thermal_CFD", + "structural_FEA", + "magnet_quench_analysis" + ], + "required_outputs": [ + "3D_TBR_and_heating", + "heat_exhaust", + "structural_margin", + "magnet_qualification" + ], + "stage": "reactor_promotion" + } + ], + "search_policy": { + "candidate_families": [ + "single_stage_nonplanar_modular_fourier_coils_with_movable_plasma_boundary", + "differentiable_winding_surface_proxy_then_filament_realization", + "spatially_constrained_wireframe_or_planar_shaping_array", + "passive_superconductor_hybrid_only_as_secondary_architecture" + ], + "forbid_bruteforce_same_family_after_rejection": true, + "minimum_relative_improvement": 0.05, + "stagnation_window": 4 + } + }, + "magnetic_autopsy": { + "decision": "family_switch_required", + "diagnostics": { + "excursion_slack_fraction_of_limit": 0.03887363150000003, + "iota_factor_to_minimum_gate": 3.8265231015219268, + "normal_field_factor_over_limit": 12.982549751999999, + "sfr4_candidate_count": 80.0, + "sfr4_combined_pass_count": 0.0 + }, + "lanes": [ + { + "lane": "direct_filament_helical_topology", + "max_violation": 0.73866615372, + "observations": [ + { + "authority": "intermediate_vacuum_biot_savart_field_line_screen", + "constraint_id": "mean_iota_min", + "lane": "direct_filament_helical_topology", + "limit": 0.25, + "lower": null, + "normalized_slack": 0.0, + "normalized_violation": 0.73866615372, + "passed": false, + "relation": "ge", + "signed_residual": 0.18466653843, + "source": "results/sfr4_integrated/...v090.json:workstreams.1_physical_coil_field.best_candidate", + "uncertainty_fraction": 0.0, + "unit": "dimensionless", + "upper": null, + "value": 0.06533346157 + }, + { + "authority": "intermediate_vacuum_biot_savart_field_line_screen", + "constraint_id": "normalized_max_excursion", + "lane": "direct_filament_helical_topology", + "limit": 0.2, + "lower": null, + "normalized_slack": 0.03887363150000003, + "normalized_violation": 0.0, + "passed": true, + "relation": "le", + "signed_residual": -0.007774726300000007, + "source": "results/sfr4_integrated/...v090.json:workstreams.1_physical_coil_field.best_candidate", + "uncertainty_fraction": 0.0, + "unit": "dimensionless", + "upper": null, + "value": 0.1922252737 + } + ] + }, + { + "lane": "held_out_hybrid_reconstruction", + "max_violation": 11.982549752, + "observations": [ + { + "authority": "intermediate_held_out_biot_savart_filament_screen", + "constraint_id": "validation_rms_Bn_over_B", + "lane": "held_out_hybrid_reconstruction", + "limit": 0.005, + "lower": null, + "normalized_slack": 0.0, + "normalized_violation": 11.982549752, + "passed": false, + "relation": "le", + "signed_residual": 0.05991274876, + "source": "results/sfr4_integrated/...v090.json:workstreams.1_physical_coil_field.held_out_hybrid_reconstruction", + "uncertainty_fraction": 0.0, + "unit": "dimensionless", + "upper": null, + "value": 0.06491274876 + } + ] + } + ], + "next_families": [ + "single_stage_nonplanar_modular_fourier_coils_with_movable_plasma_boundary", + "differentiable_winding_surface_proxy_then_filament_realization", + "spatially_constrained_wireframe_or_planar_shaping_array", + "passive_superconductor_hybrid_only_as_secondary_architecture" + ], + "rationale": [ + "The SFR-4 helical topology lane needs 3.827x its present mean transform just to reach the minimum gate.", + "That same lane retains only 3.89% normalized excursion slack before its declared nestedness ceiling.", + "The independent held-out richer basis is 12.983x above its RMS normal-field limit.", + "The topology and held-out reconstruction values come from different reduced representations and are not merged into a fictitious physical coil set.", + "The evidence rejects brute-force continuation of the present fixed helical/fixed-basis family as the preferred next move; it does not reject stellarators or fusion." + ] + }, + "promotion_status": { + "SFR5_G0_SPEC_AND_AUTOPSY": "PASS_REDUCED", + "SFR5_G1_MOVABLE_GEOMETRY_SENSITIVITIES": "NOT_RUN", + "SFR5_G2_WINDING_SURFACE_FEASIBILITY": "NOT_RUN", + "SFR5_G3_DISCRETE_NONPLANAR_COILS": "NOT_RUN", + "SFR5_G4_SINGLE_STAGE_EQUILIBRIUM_CODESIGN": "NOT_RUN", + "SFR5_G5_PARTICLE_AND_TRANSPORT": "NOT_RUN", + "SFR5_G6_HEAT_MAGNET_NEUTRONICS": "NOT_RUN", + "SFR5_G7_INTEGRATED_PLANT": "NOT_RUN", + "SFR5_G8_HARDWARE": "NOT_RUN" + }, + "rejected_family_memory": { + "evidence_ids": [ + "SFR4_PHYSICAL_COIL_SCAN_80_OF_80_REJECTED", + "SFR4_HELD_OUT_HYBRID_RECONSTRUCTION_FAIL" + ], + "family": "fixed_helical_plus_fixed_hybrid_filament_basis", + "fingerprint_sha256": "782fb74a669c8166f4ceef1ddec7090b81899bb5bcc347e62fdd931b508a2bfb", + "reason": "SFR-4 produced zero combined topology passes and the independent held-out reconstruction also failed its declared normal-field gate.", + "reopen_conditions": [ + "new_plasma_boundary_family", + "new_winding_surface_parameterization", + "new_nonplanar_coil_parameterization", + "higher_authority_solver_evidence_changes_failure_identity" + ], + "silent_reopen_allowed": false + }, + "release": "0.10.0", + "research_decision": "STOP_BRUTE_FORCE_FIXED_HELICAL_FAMILY__MOVE_TO_MOVABLE_PLASMA_BOUNDARY_WINDING_SURFACE_AND_NONPLANAR_COIL_CODESIGN__PROMOTE_ONLY_WITH_EXTERNAL_EVIDENCE", + "source_artifacts": { + "sfr4_config": "configs/reactor/sfr4_integrated_physical_promotion_a.json", + "sfr4_result": "results/sfr4_integrated/sfr4_integrated_physical_promotion_a_v090.json" + }, + "source_invariants": { + "candidate_count": 80, + "combined_pass_count": 0, + "held_out_reconstruction_pass": false, + "physical_coil_promoted": false, + "sfr4_release": "0.9.0" + }, + "study_id": "SFR5-REALITY-GRADIENT-A", + "top_level_verdict": "REALITY_GRADIENT_AUTOPSY_COMPLETE__CURRENT_MAGNETIC_FAMILY_REJECTED__ADAPTIVE_INVERSE_DESIGN_PATH_DEFINED__NO_PHYSICS_PROMOTION" +} diff --git a/sbom.spdx.json b/sbom.spdx.json index d3561eb..a16e822 100644 --- a/sbom.spdx.json +++ b/sbom.spdx.json @@ -2,17 +2,19 @@ "SPDXID": "SPDXRef-DOCUMENT", "spdxVersion": "SPDX-2.3", "dataLicense": "CC0-1.0", - "name": "IX-StellaratorForge-0.9.0-SBOM", - "documentNamespace": "https://github.com/BryceWDesign/IX-StellaratorForge/spdx/0.9.0", + "name": "IX-StellaratorForge-0.10.0-SBOM", + "documentNamespace": "https://github.com/BryceWDesign/IX-StellaratorForge/spdx/0.10.0", "creationInfo": { "created": "2026-08-22T00:00:00Z", - "creators": ["Tool: IX-StellaratorForge release preparation"] + "creators": [ + "Tool: IX-StellaratorForge release preparation" + ] }, "packages": [ { "name": "IX-StellaratorForge", "SPDXID": "SPDXRef-Package-IXStellaratorForge", - "versionInfo": "0.9.0", + "versionInfo": "0.10.0", "downloadLocation": "NOASSERTION", "filesAnalyzed": false, "licenseConcluded": "LicenseRef-IX-StellaratorForge-Eval-Only-1.1", diff --git a/schemas/reactor/sfr5_reality_gradient.schema.json b/schemas/reactor/sfr5_reality_gradient.schema.json new file mode 100644 index 0000000..01c4864 --- /dev/null +++ b/schemas/reactor/sfr5_reality_gradient.schema.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/BryceWDesign/IX-StellaratorForge/schemas/reactor/sfr5_reality_gradient.schema.json", + "title": "SFR-5 Reality Gradient and Adaptive Inverse Design", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "study_id", + "source_release", + "source_artifacts", + "constraint_pressure", + "search_policy", + "movable_design_variables", + "required_external_methods", + "reopen_conditions", + "promotion_status", + "claim_boundary" + ], + "properties": { + "schema_version": {"const": "0.10.0"}, + "study_id": {"const": "SFR5-REALITY-GRADIENT-A"}, + "source_release": {"const": "0.9.0"}, + "source_artifacts": { + "type": "object", + "required": ["sfr4_result", "sfr4_config"], + "properties": { + "sfr4_result": {"type": "string", "minLength": 1}, + "sfr4_config": {"type": "string", "minLength": 1} + } + }, + "constraint_pressure": { + "type": "object", + "required": ["rho", "normalization", "uncertainty_policy"], + "properties": { + "rho": {"type": "number", "exclusiveMinimum": 0}, + "normalization": {"type": "string", "minLength": 1}, + "uncertainty_policy": {"type": "string", "minLength": 1} + } + }, + "search_policy": { + "type": "object", + "required": ["stagnation_window", "minimum_relative_improvement", "forbid_bruteforce_same_family_after_rejection", "candidate_families"], + "properties": { + "stagnation_window": {"type": "integer", "minimum": 2}, + "minimum_relative_improvement": {"type": "number", "minimum": 0, "maximum": 1}, + "forbid_bruteforce_same_family_after_rejection": {"const": true}, + "candidate_families": {"type": "array", "minItems": 3, "uniqueItems": true, "items": {"type": "string", "minLength": 1}} + } + }, + "movable_design_variables": {"type": "array", "minItems": 4, "items": {"type": "object"}}, + "required_external_methods": {"type": "array", "minItems": 4, "items": {"type": "object"}}, + "reopen_conditions": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}}, + "promotion_status": {"type": "object", "minProperties": 2}, + "claim_boundary": { + "type": "object", + "minProperties": 1, + "additionalProperties": {"const": 0.0} + } + } +} diff --git a/scripts/generate_release.py b/scripts/generate_release.py index 3cfca1c..df6e66e 100644 --- a/scripts/generate_release.py +++ b/scripts/generate_release.py @@ -20,7 +20,8 @@ def main()->int: run('scripts/run_sfr3_field_integrity.py') run('scripts/run_sfr3_dual_boundary.py') run('scripts/run_sfr4_integrated_campaign.py') + run('scripts/run_sfr5_reality_gradient.py') run('scripts/make_manifest.py') - print('IX-StellaratorForge v0.9.0 release artifacts regenerated') + print('IX-StellaratorForge v0.10.0 release artifacts regenerated') return 0 if __name__=='__main__':raise SystemExit(main()) diff --git a/scripts/run_sfr5_reality_gradient.py b/scripts/run_sfr5_reality_gradient.py new file mode 100644 index 0000000..16299cc --- /dev/null +++ b/scripts/run_sfr5_reality_gradient.py @@ -0,0 +1,41 @@ +from __future__ import annotations + +import json +from pathlib import Path +import sys + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / "src")) + +from ix_stellaratorforge.sfr5_inverse_design import render_result_markdown, run_sfr5_campaign + + +def main() -> int: + raw = json.loads((ROOT / "configs/reactor/sfr5_reality_gradient_a.json").read_text(encoding="utf-8")) + sfr4_result = json.loads((ROOT / raw["source_artifacts"]["sfr4_result"]).read_text(encoding="utf-8")) + sfr4_config = json.loads((ROOT / raw["source_artifacts"]["sfr4_config"]).read_text(encoding="utf-8")) + result = run_sfr5_campaign(raw, sfr4_result, sfr4_config) + + result_dir = ROOT / "results/sfr5" + result_dir.mkdir(parents=True, exist_ok=True) + json_path = result_dir / "sfr5_reality_gradient_a_v0100.json" + md_path = result_dir / "SFR5_REALITY_GRADIENT_A_RESULT.md" + json_path.write_text(json.dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8", newline="\n") + md_path.write_text(render_result_markdown(result), encoding="utf-8", newline="\n") + + diag = result["magnetic_autopsy"]["diagnostics"] + print("SFR-5 REALITY GRADIENT A") + print(f"verdict: {result['top_level_verdict']}") + print(f"SFR-4 candidate count: {int(diag['sfr4_candidate_count'])}") + print(f"SFR-4 combined passes: {int(diag['sfr4_combined_pass_count'])}") + print(f"iota factor to minimum gate: {diag['iota_factor_to_minimum_gate']:.6f}x") + print(f"excursion slack: {100.0 * diag['excursion_slack_fraction_of_limit']:.6f}%") + print(f"held-out Bn/B factor over limit: {diag['normal_field_factor_over_limit']:.6f}x") + print(f"decision: {result['magnetic_autopsy']['decision']}") + print(f"wrote: {json_path.relative_to(ROOT)}") + print(f"wrote: {md_path.relative_to(ROOT)}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/src/ix_stellaratorforge/__init__.py b/src/ix_stellaratorforge/__init__.py index ac18063..d152e33 100644 --- a/src/ix_stellaratorforge/__init__.py +++ b/src/ix_stellaratorforge/__init__.py @@ -26,6 +26,10 @@ run_integrated_campaign, validate_integrated_config, ) +from .sfr5_inverse_design import ( + run_sfr5_campaign, + validate_sfr5_config, +) __all__ = [ "DTReactionLedger", @@ -51,4 +55,6 @@ "validate_dual_boundary_config", "run_integrated_campaign", "validate_integrated_config", + "run_sfr5_campaign", + "validate_sfr5_config", ] diff --git a/src/ix_stellaratorforge/architecture_search.py b/src/ix_stellaratorforge/architecture_search.py new file mode 100644 index 0000000..5290a30 --- /dev/null +++ b/src/ix_stellaratorforge/architecture_search.py @@ -0,0 +1,121 @@ +"""Adaptive SFR-5 architecture-family search controller. + +Repeated failure is treated as evidence about representation quality. The controller +can therefore request more geometry freedom or a family switch instead of silently +increasing scan density forever. +""" +from __future__ import annotations + +from dataclasses import dataclass, field +from enum import StrEnum + +from .reality_gradient import ConstraintObservation + + +class SearchAction(StrEnum): + REFINE_CURRENT_FAMILY = "refine_current_family" + ADD_DEGREES_OF_FREEDOM = "add_degrees_of_freedom" + SWITCH_ARCHITECTURE_FAMILY = "switch_architecture_family" + PROMOTE_SOLVER_AUTHORITY = "promote_solver_authority" + HOLD_FOR_MISSING_EVIDENCE = "hold_for_missing_evidence" + + +@dataclass(frozen=True, slots=True) +class IterationEvidence: + iteration: int + family: str + observations: tuple[ConstraintObservation, ...] + objective: float + + def __post_init__(self) -> None: + if self.iteration < 1: + raise ValueError("iteration must be >= 1") + if not self.family.strip(): + raise ValueError("family must be non-empty") + if not self.observations: + raise ValueError("observations must be non-empty") + + @property + def max_violation(self) -> float: + return max((x.normalized_violation for x in self.observations), default=0.0) + + @property + def failed_ids(self) -> tuple[str, ...]: + return tuple(sorted(x.constraint_id for x in self.observations if not x.passed)) + + +@dataclass(frozen=True, slots=True) +class SearchDecision: + action: SearchAction + reason: str + failed_ids: tuple[str, ...] + + +@dataclass(slots=True) +class ArchitectureSearchController: + """Detect stagnation and representation failure from evidence history.""" + + stagnation_window: int = 4 + minimum_relative_improvement: float = 0.05 + history: list[IterationEvidence] = field(default_factory=list) + + def __post_init__(self) -> None: + if self.stagnation_window < 2: + raise ValueError("stagnation_window must be >= 2") + if not 0.0 <= self.minimum_relative_improvement <= 1.0: + raise ValueError("minimum_relative_improvement must be in [0, 1]") + + def add(self, evidence: IterationEvidence) -> None: + if self.history and evidence.iteration <= self.history[-1].iteration: + raise ValueError("iterations must be strictly increasing") + self.history.append(evidence) + + def decide(self) -> SearchDecision: + if not self.history: + return SearchDecision( + SearchAction.HOLD_FOR_MISSING_EVIDENCE, + "No evaluated candidates.", + (), + ) + + latest = self.history[-1] + if latest.max_violation == 0.0: + return SearchDecision( + SearchAction.PROMOTE_SOLVER_AUTHORITY, + "Current reduced constraints pass; move to a higher-authority solver without claiming physical closure.", + latest.failed_ids, + ) + + if len(self.history) < self.stagnation_window: + return SearchDecision( + SearchAction.REFINE_CURRENT_FAMILY, + "Insufficient history to diagnose structural stagnation.", + latest.failed_ids, + ) + + window = self.history[-self.stagnation_window :] + same_family = len({x.family for x in window}) == 1 + same_failures = len({x.failed_ids for x in window}) == 1 + start = max(window[0].max_violation, 1e-12) + improvement = (window[0].max_violation - window[-1].max_violation) / start + + if same_family and same_failures and improvement < self.minimum_relative_improvement: + return SearchDecision( + SearchAction.SWITCH_ARCHITECTURE_FAMILY, + ( + f"Dominant failures persisted for {self.stagnation_window} evaluations " + f"with only {improvement:.3%} relative violation improvement." + ), + latest.failed_ids, + ) + if same_family and same_failures: + return SearchDecision( + SearchAction.ADD_DEGREES_OF_FREEDOM, + "The family is improving but the same constraints remain active; expand geometry before increasing brute-force sampling density.", + latest.failed_ids, + ) + return SearchDecision( + SearchAction.REFINE_CURRENT_FAMILY, + "Failure identity is still changing, so structural stagnation is not established.", + latest.failed_ids, + ) diff --git a/src/ix_stellaratorforge/reality_gradient.py b/src/ix_stellaratorforge/reality_gradient.py new file mode 100644 index 0000000..2f6ebf4 --- /dev/null +++ b/src/ix_stellaratorforge/reality_gradient.py @@ -0,0 +1,305 @@ +"""Fail-closed constraint-pressure primitives for SFR-5 inverse design. + +The Reality Gradient layer is deliberately solver-agnostic. It does not claim a +plasma equilibrium, confinement, buildable coils, ignition, or fusion. Its job is +to preserve constraint identity and evidence authority, quantify how badly a +candidate misses declared gates, and map those failures back onto upstream design +degrees of freedom when real sensitivities are available. + +Engineering failure is therefore retained as design information instead of being +collapsed to a bare boolean. +""" +from __future__ import annotations + +from dataclasses import asdict, dataclass, field +from enum import StrEnum +from hashlib import sha256 +import json +from typing import Callable, Iterable, Sequence + +import numpy as np + + +class Relation(StrEnum): + """Supported constraint relations.""" + + LE = "le" + GE = "ge" + RANGE = "range" + + +class ArchitectureDecision(StrEnum): + """Fail-closed architecture decisions emitted by an autopsy.""" + + CONTINUE = "continue" + HOLD = "hold" + FAMILY_SWITCH_REQUIRED = "family_switch_required" + PROMOTE_TO_HIGHER_AUTHORITY = "promote_to_higher_authority" + + +@dataclass(frozen=True, slots=True) +class ConstraintObservation: + """One measured constraint in one explicit evidence lane.""" + + constraint_id: str + lane: str + value: float + relation: Relation + limit: float | None = None + lower: float | None = None + upper: float | None = None + unit: str = "dimensionless" + authority: str = "unknown" + source: str = "unknown" + uncertainty_fraction: float = 0.0 + + def __post_init__(self) -> None: + if not self.constraint_id.strip() or not self.lane.strip(): + raise ValueError("constraint_id and lane must be non-empty") + if not np.isfinite(self.value): + raise ValueError("constraint value must be finite") + if self.uncertainty_fraction < 0: + raise ValueError("uncertainty_fraction must be non-negative") + if self.relation in (Relation.LE, Relation.GE): + if self.limit is None or not np.isfinite(self.limit): + raise ValueError("LE/GE constraints require a finite limit") + elif self.relation is Relation.RANGE: + if ( + self.lower is None + or self.upper is None + or not np.isfinite(self.lower) + or not np.isfinite(self.upper) + or self.lower >= self.upper + ): + raise ValueError("RANGE requires finite lower < upper") + + @property + def passed(self) -> bool: + if self.relation is Relation.LE: + return self.value <= float(self.limit) + if self.relation is Relation.GE: + return self.value >= float(self.limit) + return float(self.lower) <= self.value <= float(self.upper) + + @property + def signed_residual(self) -> float: + """Return c(x) in canonical inequality form c(x) <= 0.""" + + if self.relation is Relation.LE: + return self.value - float(self.limit) + if self.relation is Relation.GE: + return float(self.limit) - self.value + assert self.lower is not None and self.upper is not None + return max(self.lower - self.value, self.value - self.upper) + + @property + def scale(self) -> float: + if self.relation in (Relation.LE, Relation.GE): + return max(abs(float(self.limit)), 1e-12) + assert self.lower is not None and self.upper is not None + return max(abs(self.lower), abs(self.upper), self.upper - self.lower, 1e-12) + + @property + def normalized_violation(self) -> float: + return max(0.0, self.signed_residual) / self.scale + + @property + def normalized_slack(self) -> float: + return max(0.0, -self.signed_residual) / self.scale + + def to_dict(self) -> dict[str, object]: + payload = asdict(self) + payload["relation"] = self.relation.value + payload["passed"] = self.passed + payload["signed_residual"] = self.signed_residual + payload["normalized_violation"] = self.normalized_violation + payload["normalized_slack"] = self.normalized_slack + return payload + + +@dataclass(frozen=True, slots=True) +class LaneAutopsy: + """Constraint observations that genuinely belong to one model/evidence lane.""" + + lane: str + observations: tuple[ConstraintObservation, ...] + + @property + def failures(self) -> tuple[ConstraintObservation, ...]: + return tuple(x for x in self.observations if not x.passed) + + @property + def passes(self) -> tuple[ConstraintObservation, ...]: + return tuple(x for x in self.observations if x.passed) + + @property + def max_violation(self) -> float: + return max((x.normalized_violation for x in self.observations), default=0.0) + + def dominant_failure(self) -> ConstraintObservation | None: + if not self.failures: + return None + return max(self.failures, key=lambda x: x.normalized_violation) + + +@dataclass(slots=True) +class AugmentedLagrangianState: + """Multiplier state for normalized inequality constraints c_i(x) <= 0.""" + + rho: float = 2.0 + multipliers: dict[str, float] = field(default_factory=dict) + + def update(self, observations: Iterable[ConstraintObservation]) -> None: + if self.rho <= 0: + raise ValueError("rho must be positive") + for obs in observations: + lam = self.multipliers.get(obs.constraint_id, 0.0) + normalized_c = obs.signed_residual / obs.scale + self.multipliers[obs.constraint_id] = max(0.0, lam + self.rho * normalized_c) + + def pressure(self, observation: ConstraintObservation) -> float: + """Return active normalized pressure including declared uncertainty.""" + + c = observation.signed_residual / observation.scale + lam = self.multipliers.get(observation.constraint_id, 0.0) + uncertainty = 1.0 + observation.uncertainty_fraction + return max(0.0, lam + self.rho * c) * uncertainty + + +@dataclass(frozen=True, slots=True) +class SensitivityResult: + variable_names: tuple[str, ...] + constraint_ids: tuple[str, ...] + jacobian: np.ndarray + + def __post_init__(self) -> None: + expected = (len(self.constraint_ids), len(self.variable_names)) + if self.jacobian.shape != expected: + raise ValueError(f"jacobian shape {self.jacobian.shape} != {expected}") + if not np.all(np.isfinite(self.jacobian)): + raise ValueError("jacobian must be finite") + + +def finite_difference_sensitivities( + x: Sequence[float], + *, + variable_names: Sequence[str], + evaluator: Callable[[np.ndarray], Sequence[ConstraintObservation]], + relative_step: float = 1e-4, +) -> SensitivityResult: + """Finite-difference Jacobian of normalized signed constraint residuals. + + Production differentiable solvers should provide analytic or automatic + derivatives. This deterministic fallback exists for black-box low-authority + components and for testing the controller contract. + """ + + point = np.asarray(x, dtype=float) + if point.ndim != 1 or len(point) != len(variable_names): + raise ValueError("x and variable_names must have equal 1-D length") + if not np.all(np.isfinite(point)): + raise ValueError("x must be finite") + if relative_step <= 0: + raise ValueError("relative_step must be positive") + + base = tuple(evaluator(point.copy())) + ids = tuple(o.constraint_id for o in base) + if not ids or len(set(ids)) != len(ids): + raise ValueError("evaluator must return unique constraint ids") + + def normalized_map(obs: Sequence[ConstraintObservation]) -> dict[str, float]: + return {o.constraint_id: o.signed_residual / o.scale for o in obs} + + jac = np.zeros((len(base), len(point)), dtype=float) + for j in range(len(point)): + h = relative_step * max(1.0, abs(point[j])) + xp = point.copy() + xm = point.copy() + xp[j] += h + xm[j] -= h + plus = normalized_map(tuple(evaluator(xp))) + minus = normalized_map(tuple(evaluator(xm))) + if set(plus) != set(ids) or set(minus) != set(ids): + raise ValueError("evaluator changed constraint identity across perturbation") + for i, cid in enumerate(ids): + jac[i, j] = (plus[cid] - minus[cid]) / (2.0 * h) + return SensitivityResult(tuple(variable_names), ids, jac) + + +def backward_reality_gradient( + observations: Sequence[ConstraintObservation], + state: AugmentedLagrangianState, + sensitivity: SensitivityResult, +) -> dict[str, float]: + """Map active constraint pressure backward onto upstream design variables.""" + + obs_by_id = {o.constraint_id: o for o in observations} + if set(obs_by_id) != set(sensitivity.constraint_ids): + raise ValueError("observation ids do not match sensitivity ids") + pressure = np.array( + [state.pressure(obs_by_id[cid]) for cid in sensitivity.constraint_ids], + dtype=float, + ) + grad = sensitivity.jacobian.T @ pressure + return { + name: float(value) + for name, value in zip(sensitivity.variable_names, grad, strict=True) + } + + +@dataclass(frozen=True, slots=True) +class RejectedFamilyRecord: + """Auditable record preventing silent resurrection of a rejected family.""" + + family: str + reason: str + evidence_ids: tuple[str, ...] + reopen_conditions: tuple[str, ...] + fingerprint: str + + @classmethod + def create( + cls, + *, + family: str, + reason: str, + evidence_ids: Sequence[str], + reopen_conditions: Sequence[str], + ) -> "RejectedFamilyRecord": + if not family.strip() or not reason.strip() or not evidence_ids: + raise ValueError("family, reason, and at least one evidence id are required") + payload = { + "family": family, + "reason": reason, + "evidence_ids": list(evidence_ids), + "reopen_conditions": list(reopen_conditions), + } + digest = sha256( + json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8") + ).hexdigest() + return cls( + family, + reason, + tuple(evidence_ids), + tuple(reopen_conditions), + digest, + ) + + +@dataclass(slots=True) +class ArchitectureMemory: + """Minimal fail-closed family rejection memory.""" + + rejected: dict[str, RejectedFamilyRecord] = field(default_factory=dict) + + def reject(self, record: RejectedFamilyRecord) -> None: + self.rejected[record.family] = record + + def may_reopen(self, family: str, supplied_new_evidence: Sequence[str]) -> bool: + record = self.rejected.get(family) + if record is None: + return True + supplied = set(supplied_new_evidence) + return bool(supplied) and any( + condition in supplied for condition in record.reopen_conditions + ) diff --git a/src/ix_stellaratorforge/sfr5_inverse_design.py b/src/ix_stellaratorforge/sfr5_inverse_design.py new file mode 100644 index 0000000..2771116 --- /dev/null +++ b/src/ix_stellaratorforge/sfr5_inverse_design.py @@ -0,0 +1,315 @@ +"""SFR-5 Reality Gradient and adaptive inverse-design campaign. + +SFR-5 does not run a production coil/plasma optimizer in the base release. It turns +the committed SFR-4 magnetic failure into a reproducible, provenance-preserving +architecture decision and defines the exact evidence required before any replacement +coil family may be promoted. +""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any + +from .reality_gradient import ( + ArchitectureDecision, + ArchitectureMemory, + AugmentedLagrangianState, + ConstraintObservation, + LaneAutopsy, + RejectedFamilyRecord, + Relation, +) + +PASS_VERDICT = ( + "REALITY_GRADIENT_AUTOPSY_COMPLETE__CURRENT_MAGNETIC_FAMILY_REJECTED__" + "ADAPTIVE_INVERSE_DESIGN_PATH_DEFINED__NO_PHYSICS_PROMOTION" +) +CURRENT_FAMILY = "fixed_helical_plus_fixed_hybrid_filament_basis" + + +@dataclass(frozen=True, slots=True) +class MagneticAutopsy: + lanes: tuple[LaneAutopsy, ...] + decision: ArchitectureDecision + rationale: tuple[str, ...] + next_families: tuple[str, ...] + diagnostics: dict[str, float] + + def to_dict(self) -> dict[str, Any]: + return { + "lanes": [ + { + "lane": lane.lane, + "observations": [obs.to_dict() for obs in lane.observations], + "max_violation": lane.max_violation, + } + for lane in self.lanes + ], + "decision": self.decision.value, + "rationale": list(self.rationale), + "next_families": list(self.next_families), + "diagnostics": self.diagnostics, + } + + +def validate_sfr5_config(raw: dict[str, Any]) -> tuple[str, ...]: + errors: list[str] = [] + try: + if raw.get("schema_version") != "0.10.0": + errors.append("schema_version must be 0.10.0") + if raw.get("study_id") != "SFR5-REALITY-GRADIENT-A": + errors.append("study_id must be SFR5-REALITY-GRADIENT-A") + if raw.get("source_release") != "0.9.0": + errors.append("source_release must remain 0.9.0") + + sources = raw["source_artifacts"] + for key in ("sfr4_result", "sfr4_config"): + if not str(sources.get(key, "")).strip(): + errors.append(f"source_artifacts.{key} must be non-empty") + + search = raw["search_policy"] + if int(search["stagnation_window"]) < 2: + errors.append("search_policy.stagnation_window must be >= 2") + improvement = float(search["minimum_relative_improvement"]) + if not 0.0 <= improvement <= 1.0: + errors.append("search_policy.minimum_relative_improvement must be in [0, 1]") + families = list(search["candidate_families"]) + if len(families) < 3 or len(set(families)) != len(families): + errors.append("search_policy.candidate_families must contain >=3 unique families") + if not bool(search["forbid_bruteforce_same_family_after_rejection"]): + errors.append("rejected-family brute-force continuation must remain forbidden") + + dof_groups = {str(x["group"]) for x in raw["movable_design_variables"]} + required_groups = { + "plasma_boundary", + "winding_surface", + "coil_geometry", + "coil_currents", + } + if not required_groups.issubset(dof_groups): + errors.append("movable_design_variables omit required inverse-design groups") + + claim = raw["claim_boundary"] + if not claim or any(float(value) != 0.0 for value in claim.values()): + errors.append("all SFR-5 claim-boundary credits must remain exactly zero") + + gates = raw["promotion_status"] + if gates.get("SFR5_G0_SPEC_AND_AUTOPSY") != "PASS_REDUCED": + errors.append("SFR5_G0_SPEC_AND_AUTOPSY must be PASS_REDUCED") + for gate, status in gates.items(): + if gate != "SFR5_G0_SPEC_AND_AUTOPSY" and status != "NOT_RUN": + errors.append(f"{gate} must remain NOT_RUN in the base SFR-5 release") + except (KeyError, TypeError, ValueError) as exc: + errors.append(f"invalid SFR-5 config: {exc}") + return tuple(errors) + + +def magnetic_autopsy_from_sfr4( + sfr4_result: dict[str, Any], + sfr4_config: dict[str, Any], + *, + next_families: tuple[str, ...], +) -> MagneticAutopsy: + """Derive the SFR-5 diagnosis from committed SFR-4 evidence and gates.""" + + if sfr4_result.get("release") != "0.9.0": + raise ValueError("SFR-5 source result must be the committed v0.9.0 SFR-4 result") + coil = sfr4_result["workstreams"]["1_physical_coil_field"] + scan = sfr4_config["coil_field_scan"] + best = coil["best_candidate"] + reconstruction = coil["held_out_hybrid_reconstruction"] + + iota_min = float(scan["iota_acceptance"][0]) + excursion_limit = float(scan["max_excursion_fraction"]) + bn_limit = float(scan["normal_field_rms_limit"]) + + topology_lane = "direct_filament_helical_topology" + reconstruction_lane = "held_out_hybrid_reconstruction" + topology = LaneAutopsy( + lane=topology_lane, + observations=( + ConstraintObservation( + constraint_id="mean_iota_min", + lane=topology_lane, + value=float(best["mean_iota"]), + relation=Relation.GE, + limit=iota_min, + authority=str(best["authority"]), + source="results/sfr4_integrated/...v090.json:workstreams.1_physical_coil_field.best_candidate", + ), + ConstraintObservation( + constraint_id="normalized_max_excursion", + lane=topology_lane, + value=float(best["normalized_max_excursion_over_a"]), + relation=Relation.LE, + limit=excursion_limit, + authority=str(best["authority"]), + source="results/sfr4_integrated/...v090.json:workstreams.1_physical_coil_field.best_candidate", + ), + ), + ) + held_out = LaneAutopsy( + lane=reconstruction_lane, + observations=( + ConstraintObservation( + constraint_id="validation_rms_Bn_over_B", + lane=reconstruction_lane, + value=float(reconstruction["validation_rms_Bn_over_B"]), + relation=Relation.LE, + limit=bn_limit, + authority=str(reconstruction["authority"]), + source="results/sfr4_integrated/...v090.json:workstreams.1_physical_coil_field.held_out_hybrid_reconstruction", + ), + ), + ) + + iota_obs, excursion_obs = topology.observations + bn_obs = held_out.observations[0] + if iota_obs.value <= 0 or bn_limit <= 0: + raise ValueError("SFR-4 magnetic evidence is outside SFR-5 diagnostic domain") + + diagnostics = { + "iota_factor_to_minimum_gate": iota_min / iota_obs.value, + "excursion_slack_fraction_of_limit": excursion_obs.normalized_slack, + "normal_field_factor_over_limit": bn_obs.value / bn_limit, + "sfr4_candidate_count": float(coil["candidate_count"]), + "sfr4_combined_pass_count": float(coil["combined_pass_count"]), + } + rationale = ( + f"The SFR-4 helical topology lane needs {diagnostics['iota_factor_to_minimum_gate']:.3f}x its present mean transform just to reach the minimum gate.", + f"That same lane retains only {100.0 * diagnostics['excursion_slack_fraction_of_limit']:.2f}% normalized excursion slack before its declared nestedness ceiling.", + f"The independent held-out richer basis is {diagnostics['normal_field_factor_over_limit']:.3f}x above its RMS normal-field limit.", + "The topology and held-out reconstruction values come from different reduced representations and are not merged into a fictitious physical coil set.", + "The evidence rejects brute-force continuation of the present fixed helical/fixed-basis family as the preferred next move; it does not reject stellarators or fusion.", + ) + return MagneticAutopsy( + lanes=(topology, held_out), + decision=ArchitectureDecision.FAMILY_SWITCH_REQUIRED, + rationale=rationale, + next_families=next_families, + diagnostics=diagnostics, + ) + + +def run_sfr5_campaign( + raw: dict[str, Any], + sfr4_result: dict[str, Any], + sfr4_config: dict[str, Any], +) -> dict[str, Any]: + errors = validate_sfr5_config(raw) + if errors: + raise ValueError("; ".join(errors)) + + next_families = tuple(str(x) for x in raw["search_policy"]["candidate_families"]) + autopsy = magnetic_autopsy_from_sfr4( + sfr4_result, + sfr4_config, + next_families=next_families, + ) + + observations = tuple( + obs for lane in autopsy.lanes for obs in lane.observations + ) + pressure_state = AugmentedLagrangianState(rho=float(raw["constraint_pressure"]["rho"])) + pressure_state.update(observations) + pressure = { + obs.constraint_id: pressure_state.pressure(obs) + for obs in observations + } + + record = RejectedFamilyRecord.create( + family=CURRENT_FAMILY, + reason="SFR-4 produced zero combined topology passes and the independent held-out reconstruction also failed its declared normal-field gate.", + evidence_ids=( + "SFR4_PHYSICAL_COIL_SCAN_80_OF_80_REJECTED", + "SFR4_HELD_OUT_HYBRID_RECONSTRUCTION_FAIL", + ), + reopen_conditions=tuple(str(x) for x in raw["reopen_conditions"]), + ) + memory = ArchitectureMemory() + memory.reject(record) + + source_coil = sfr4_result["workstreams"]["1_physical_coil_field"] + source_invariants = { + "sfr4_release": sfr4_result["release"], + "candidate_count": source_coil["candidate_count"], + "combined_pass_count": source_coil["combined_pass_count"], + "physical_coil_promoted": source_coil["physical_coil_promoted"], + "held_out_reconstruction_pass": source_coil["held_out_hybrid_reconstruction"][ + "passes_reconstruction_screen" + ], + } + + return { + "release": "0.10.0", + "study_id": raw["study_id"], + "top_level_verdict": PASS_VERDICT, + "source_artifacts": raw["source_artifacts"], + "source_invariants": source_invariants, + "magnetic_autopsy": autopsy.to_dict(), + "constraint_pressure": { + "method": "normalized_augmented_lagrangian_pressure_without_fabricated_geometry_gradient", + "rho": pressure_state.rho, + "multipliers": dict(sorted(pressure_state.multipliers.items())), + "active_pressure": dict(sorted(pressure.items())), + "geometry_sensitivity_status": "NOT_RUN__REQUIRES_REAL_MOVABLE_GEOMETRY_EVALUATOR", + "backward_reality_gradient_status": "NOT_COMPUTED__NO_FAKE_SENSITIVITY_CREDIT", + }, + "rejected_family_memory": { + "family": record.family, + "reason": record.reason, + "evidence_ids": list(record.evidence_ids), + "reopen_conditions": list(record.reopen_conditions), + "fingerprint_sha256": record.fingerprint, + "silent_reopen_allowed": False, + }, + "inverse_design_program": { + "movable_design_variables": raw["movable_design_variables"], + "candidate_families": list(next_families), + "primary_next_family": next_families[0], + "search_policy": raw["search_policy"], + "required_external_methods": raw["required_external_methods"], + }, + "promotion_status": raw["promotion_status"], + "claim_boundary": raw["claim_boundary"], + "earned_fusion_progress_credit_fraction": 0.0, + "research_decision": ( + "STOP_BRUTE_FORCE_FIXED_HELICAL_FAMILY__MOVE_TO_MOVABLE_PLASMA_BOUNDARY_" + "WINDING_SURFACE_AND_NONPLANAR_COIL_CODESIGN__PROMOTE_ONLY_WITH_EXTERNAL_EVIDENCE" + ), + } + + +def render_result_markdown(result: dict[str, Any]) -> str: + diag = result["magnetic_autopsy"]["diagnostics"] + lines = [ + "# SFR-5 Reality Gradient and Adaptive Inverse Design A", + "", + "## Executed result", + "", + f"Top-level verdict: `{result['top_level_verdict']}`", + "", + "SFR-5 derives its diagnosis from the committed v0.9 SFR-4 magnetic result and its declared thresholds. It does not merge the direct-filament topology lane with the independent held-out reconstruction lane.", + "", + f"- SFR-4 direct-filament cases: **{int(diag['sfr4_candidate_count'])}**.", + f"- Combined topology passes: **{int(diag['sfr4_combined_pass_count'])}**.", + f"- Transform factor required merely to reach the minimum iota gate: **{diag['iota_factor_to_minimum_gate']:.4f}x**.", + f"- Remaining normalized excursion slack: **{100.0 * diag['excursion_slack_fraction_of_limit']:.3f}%** of the declared limit.", + f"- Held-out RMS normal-field error relative to its limit: **{diag['normal_field_factor_over_limit']:.4f}x**.", + "", + "## Decision", + "", + "The present fixed helical plus fixed hybrid filament-basis family is rejected as the preferred next search family. The next program must allow the plasma boundary, winding surface, nonplanar coil geometry, and currents to move together under explicit engineering constraints.", + "", + "The primary next family is `single_stage_nonplanar_modular_fourier_coils_with_movable_plasma_boundary`. Winding-surface proxy/global optimization, discrete filament realization, finite-beta equilibrium, particle/transport checks, 3-D neutronics, magnet engineering, and hardware remain promotion gates rather than assumed capabilities.", + "", + "## Reality Gradient status", + "", + "SFR-5 computes normalized constraint pressure from the existing evidence but deliberately does **not** fabricate a geometry gradient. A backward gradient is only valid after a real movable-geometry evaluator supplies analytic, automatic-differentiation, or controlled finite-difference sensitivities.", + "", + "## Claim boundary", + "", + "This release does not demonstrate a viable replacement coil set, finite-beta equilibrium, kinetic confinement, TBR, ignition, net-electric power, magnet qualification, safety qualification, or hardware operation. Earned fusion-progress credit remains exactly zero.", + "", + ] + return "\n".join(lines) diff --git a/tests/reactor/test_sfr4_integrated_campaign.py b/tests/reactor/test_sfr4_integrated_campaign.py index 3bb636c..ae28ed2 100644 --- a/tests/reactor/test_sfr4_integrated_campaign.py +++ b/tests/reactor/test_sfr4_integrated_campaign.py @@ -119,7 +119,12 @@ def test_top_level_pass_is_reduced_campaign_only_with_zero_fusion_credit(): def test_persisted_result_matches_recomputation(): - expected = _result() + expected = dict(_result()) path = ROOT / "results/sfr4_integrated/sfr4_integrated_physical_promotion_a_v090.json" - persisted = json.loads(path.read_text(encoding="utf-8")) + persisted = dict(json.loads(path.read_text(encoding="utf-8"))) + # Optional-package discovery is runtime metadata, not scientific evidence. + # The GitHub release environment records the committed availability map; extra + # locally installed packages must not invalidate the deterministic campaign core. + expected.pop("solver_availability", None) + persisted.pop("solver_availability", None) assert persisted == expected diff --git a/tests/reactor/test_sfr5_reality_gradient.py b/tests/reactor/test_sfr5_reality_gradient.py new file mode 100644 index 0000000..3781601 --- /dev/null +++ b/tests/reactor/test_sfr5_reality_gradient.py @@ -0,0 +1,157 @@ +from __future__ import annotations + +import json +from pathlib import Path + +import numpy as np + +from ix_stellaratorforge.architecture_search import ( + ArchitectureSearchController, + IterationEvidence, + SearchAction, +) +from ix_stellaratorforge.reality_gradient import ( + ArchitectureMemory, + AugmentedLagrangianState, + ConstraintObservation, + RejectedFamilyRecord, + Relation, + backward_reality_gradient, + finite_difference_sensitivities, +) +from ix_stellaratorforge.sfr5_inverse_design import ( + CURRENT_FAMILY, + PASS_VERDICT, + magnetic_autopsy_from_sfr4, + run_sfr5_campaign, + validate_sfr5_config, +) + +ROOT = Path(__file__).resolve().parents[2] + + +def _raw() -> dict: + return json.loads((ROOT / "configs/reactor/sfr5_reality_gradient_a.json").read_text(encoding="utf-8")) + + +def _sfr4_result() -> dict: + return json.loads((ROOT / "results/sfr4_integrated/sfr4_integrated_physical_promotion_a_v090.json").read_text(encoding="utf-8")) + + +def _sfr4_config() -> dict: + return json.loads((ROOT / "configs/reactor/sfr4_integrated_physical_promotion_a.json").read_text(encoding="utf-8")) + + +def _result() -> dict: + return run_sfr5_campaign(_raw(), _sfr4_result(), _sfr4_config()) + + +def test_sfr5_config_is_fail_closed_and_declares_movable_geometry() -> None: + raw = _raw() + assert validate_sfr5_config(raw) == () + groups = {item["group"] for item in raw["movable_design_variables"]} + assert {"plasma_boundary", "winding_surface", "coil_geometry", "coil_currents"} <= groups + assert all(value == 0.0 for value in raw["claim_boundary"].values()) + assert all( + status == "NOT_RUN" + for gate, status in raw["promotion_status"].items() + if gate != "SFR5_G0_SPEC_AND_AUTOPSY" + ) + + +def test_autopsy_is_derived_from_sfr4_evidence_not_magic_numbers() -> None: + raw = _raw() + result = magnetic_autopsy_from_sfr4( + _sfr4_result(), + _sfr4_config(), + next_families=tuple(raw["search_policy"]["candidate_families"]), + ) + diag = result.diagnostics + assert np.isclose(diag["iota_factor_to_minimum_gate"], 3.8265231015) + assert np.isclose(diag["normal_field_factor_over_limit"], 12.982549752) + assert np.isclose(diag["excursion_slack_fraction_of_limit"], 0.0388736315) + assert result.lanes[0].lane != result.lanes[1].lane + + +def test_sfr5_rejects_current_family_without_rejecting_stellarators() -> None: + result = _result() + assert result["top_level_verdict"] == PASS_VERDICT + assert result["magnetic_autopsy"]["decision"] == "family_switch_required" + assert result["source_invariants"]["candidate_count"] == 80 + assert result["source_invariants"]["combined_pass_count"] == 0 + assert result["rejected_family_memory"]["family"] == CURRENT_FAMILY + assert result["rejected_family_memory"]["silent_reopen_allowed"] is False + assert result["earned_fusion_progress_credit_fraction"] == 0.0 + + +def test_sfr5_does_not_fabricate_geometry_gradient() -> None: + result = _result() + pressure = result["constraint_pressure"] + assert pressure["active_pressure"]["mean_iota_min"] > 0.0 + assert pressure["active_pressure"]["validation_rms_Bn_over_B"] > 0.0 + assert pressure["active_pressure"]["normalized_max_excursion"] == 0.0 + assert pressure["geometry_sensitivity_status"].startswith("NOT_RUN") + assert pressure["backward_reality_gradient_status"].startswith("NOT_COMPUTED") + + +def test_persisted_sfr5_result_matches_recomputation() -> None: + persisted = json.loads((ROOT / "results/sfr5/sfr5_reality_gradient_a_v0100.json").read_text(encoding="utf-8")) + assert persisted == _result() + + +def test_augmented_lagrangian_and_black_box_sensitivity_contract() -> None: + def evaluate(x: np.ndarray) -> tuple[ConstraintObservation, ...]: + return ( + ConstraintObservation("sum", "toy", x[0] + 2.0 * x[1], Relation.LE, limit=1.0), + ConstraintObservation("floor", "toy", x[0], Relation.GE, limit=0.4), + ) + + point = np.array([0.8, 0.3]) + observations = evaluate(point) + sensitivity = finite_difference_sensitivities( + point, + variable_names=("x0", "x1"), + evaluator=evaluate, + ) + state = AugmentedLagrangianState(rho=2.0) + state.update(observations) + gradient = backward_reality_gradient(observations, state, sensitivity) + assert gradient["x0"] > 0.0 + assert gradient["x1"] > gradient["x0"] + + +def test_rejected_family_requires_declared_new_evidence_to_reopen() -> None: + record = RejectedFamilyRecord.create( + family="old_family", + reason="failed", + evidence_ids=("E1",), + reopen_conditions=("new_geometry", "new_solver_evidence"), + ) + memory = ArchitectureMemory() + memory.reject(record) + assert not memory.may_reopen("old_family", ()) + assert not memory.may_reopen("old_family", ("more_of_same",)) + assert memory.may_reopen("old_family", ("new_geometry",)) + assert memory.may_reopen("unseen_family", ()) + + +def test_search_controller_switches_stagnant_family_and_promotes_clean_lane() -> None: + controller = ArchitectureSearchController(stagnation_window=4, minimum_relative_improvement=0.05) + for idx, value in enumerate((0.10, 0.099, 0.0985, 0.098), start=1): + obs = (ConstraintObservation("bn", "hybrid", value, Relation.LE, limit=0.005),) + controller.add(IterationEvidence(idx, "fixed_hybrid_basis", obs, objective=value)) + assert controller.decide().action is SearchAction.SWITCH_ARCHITECTURE_FAMILY + + clean = ArchitectureSearchController() + clean.add( + IterationEvidence( + 1, + "modular", + ( + ConstraintObservation("iota", "candidate", 0.4, Relation.RANGE, lower=0.25, upper=0.8), + ConstraintObservation("excursion", "candidate", 0.1, Relation.LE, limit=0.2), + ), + objective=0.1, + ) + ) + assert clean.decide().action is SearchAction.PROMOTE_SOLVER_AUTHORITY