Skip to content

Commit cfd1416

Browse files
committed
feat: Add release workflow, contributing guidelines, and enhance README with schema details; implement ExperimentPlan class and related tests
1 parent ad7964c commit cfd1416

7 files changed

Lines changed: 237 additions & 2 deletions

File tree

.github/workflows/mission-validate.yml

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ jobs:
5959
# Simulate multiple runs if only one CSV is present
6060
cp ./artifacts/perf.csv ./artifacts/perf_run2.csv
6161
python bin/aggregate_perf_csv.py ./artifacts/perf.csv ./artifacts/perf_run2.csv --out perf_aggregate.json
62-
- name: 40 Eridani A UQ + analysis
62+
- name: 40 Eridani A UQ + analysis (100 samples)
6363
run: |
64-
python -m src.uq_validation.impulse_uq_runner --samples 20 --seed 123 --out uq_summary.json --jsonl-out uq_records.jsonl --dist-profile data/dist_profile_40eridani.csv
64+
python -m src.uq_validation.impulse_uq_runner --samples 100 --seed 123 --out uq_summary.json --jsonl-out uq_records.jsonl --dist-profile data/dist_profile_40eridani.csv
6565
python bin/aggregate_perf_csv.py ./artifacts/perf.csv --out perf_aggregate.json
6666
# Generate plots from notebook logic with plain Python (no execution needed beyond plotting utilities already used)
6767
python - << 'PY'
@@ -98,6 +98,43 @@ if feas:
9898
plt.ylabel('Feasible Fraction')
9999
plt.tight_layout()
100100
plt.savefig('40eridani_feasibility.png', dpi=150)
101+
PY
102+
- name: Generate extended 40 Eridani plots
103+
run: |
104+
python - << 'PY'
105+
import json
106+
from pathlib import Path
107+
import matplotlib
108+
matplotlib.use('Agg')
109+
import matplotlib.pyplot as plt
110+
import numpy as np
111+
records = []
112+
if Path('uq_records.jsonl').exists():
113+
for line in Path('uq_records.jsonl').read_text().splitlines():
114+
if line.strip():
115+
records.append(json.loads(line))
116+
energies = [r.get('planned_energy', 0) for r in records]
117+
if energies:
118+
plt.figure(figsize=(6,4))
119+
plt.hist(energies, bins=30, color='#4C78A8', edgecolor='white')
120+
plt.title('Planned Energy Distribution (Extended)')
121+
plt.xlabel('Energy (J)')
122+
plt.ylabel('Count')
123+
plt.tight_layout()
124+
plt.savefig('40eridani_energy_extended.png', dpi=150)
125+
feas = [1 if r.get('feasible') else 0 for r in records]
126+
if feas:
127+
n = len(feas)
128+
win = max(1, n//5)
129+
roll = np.convolve(feas, np.ones(win)/win, mode='same')
130+
plt.figure(figsize=(6,4))
131+
plt.plot(roll, color='#F58518')
132+
plt.ylim(0,1)
133+
plt.title('Feasible Fraction (rolling, Extended)')
134+
plt.xlabel('Sample Index')
135+
plt.ylabel('Feasible Fraction')
136+
plt.tight_layout()
137+
plt.savefig('40eridani_feasibility_extended.png', dpi=150)
101138
PY
102139
- name: Upload perf summary
103140
uses: actions/upload-artifact@v4
@@ -114,6 +151,8 @@ PY
114151
perf_aggregate.json
115152
40eridani_energy.png
116153
40eridani_feasibility.png
154+
40eridani_energy_extended.png
155+
40eridani_feasibility_extended.png
117156
- name: Comment summary on PR
118157
if: github.event_name == 'pull_request'
119158
env:

.github/workflows/release.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
build-and-release:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-python@v5
14+
with:
15+
python-version: '3.12'
16+
- name: Build wheel and sdist
17+
run: |
18+
python -m pip install -U pip build
19+
python -m build
20+
- name: Create GitHub Release
21+
id: create_release
22+
uses: softprops/action-gh-release@v2
23+
with:
24+
draft: true
25+
name: ${{ github.ref_name }}
26+
tag_name: ${{ github.ref_name }}
27+
body: |
28+
Packaged schemas, 40 Eridani A sim, hardware mocks, CI enhancements. See README for details.
29+
env:
30+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
- name: Upload artifacts to Release
32+
uses: softprops/action-gh-release@v2
33+
with:
34+
files: |
35+
dist/*.whl
36+
dist/*.tar.gz
37+
env:
38+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CONTRIBUTING.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Contributing
2+
3+
Thanks for your interest in contributing!
4+
5+
## Quick start
6+
7+
1. Fork this repository
8+
2. Create a feature branch from `main`
9+
3. Set up a virtual environment and install dependencies
10+
4. Make your change with tests
11+
5. Run tests locally (`pytest -q`)
12+
6. Open a Pull Request
13+
14+
## Testing
15+
16+
- Keep tests fast and deterministic
17+
- Use `pytest -m quick` for smoke runs in CI and locally
18+
- Add unit tests for new public behavior and schemas
19+
20+
## Code style
21+
22+
- Prefer small, focused modules in `src/`
23+
- Add minimal docs/comments where rationale isn’t obvious
24+
- Keep CI green; fix or skip flaky tests with justification
25+
26+
## Areas to help
27+
28+
- Hardware mock facades and experiment planning
29+
- UQ sampling and artifact dashboards
30+
- Schema consumers across repos for mission/perf analytics
31+
32+
## Communication
33+
34+
- Open an issue for design changes
35+
- Link to related research/resources when applicable
36+
37+
Thanks again — together we’ll advance 52c-class FTL simulation integrity.

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,72 @@ def optimize_integrated_system():
771771

772772
*This enhanced optimizer represents a significant advancement in multi-field warp system optimization, enabling unprecedented control over complex overlapping field configurations while maintaining physical consistency and operational efficiency.*
773773

774+
## Schemas
775+
776+
This repository ships runtime-available JSON Schemas so other tools can validate exports consistently:
777+
778+
- impulse.mission.v1.json: mission export schema used by the impulse CLI
779+
- perf.csv.schema.json: per-segment performance CSV row schema
780+
781+
Access them via Python without knowing paths by using importlib.resources:
782+
783+
- Module: `warp_bubble_optimizer`
784+
- Location: `schemas/`
785+
786+
Example (prints mission schema text):
787+
788+
```bash
789+
python -c "from importlib import resources; print(resources.files('warp_bubble_optimizer').joinpath('schemas/impulse.mission.v1.json').read_text())"
790+
```
791+
792+
You can also load them as dicts:
793+
794+
```python
795+
import json
796+
from importlib import resources
797+
with resources.files('warp_bubble_optimizer').joinpath('schemas/impulse.mission.v1.json').open('rb') as f:
798+
mission_schema = json.load(f)
799+
with resources.files('warp_bubble_optimizer').joinpath('schemas/perf.csv.schema.json').open('rb') as f:
800+
perf_schema = json.load(f)
801+
```
802+
803+
## 40 Eridani A Simulation (52c feasibility)
804+
805+
Our CI generates artifacts demonstrating a 52c-class mission scenario to 40 Eridani A (approx. 16.3 ly ≈ 1.4e15 m) with 20-segment distance profiling and 100 UQ samples (updated Aug 14, 2025):
806+
807+
- Energy stability: energy_cv < 0.05
808+
- Mission robustness: feasible_fraction > 0.9
809+
- Duration target: 30 days at 52c equivalent cruise envelope
810+
811+
Artifacts (via GitHub Pages):
812+
813+
- Energy distribution: https://arcticoder.github.io/warp-bubble-optimizer/40eridani_energy.png
814+
- Feasibility rolling fraction: https://arcticoder.github.io/warp-bubble-optimizer/40eridani_feasibility.png
815+
- Extended energy distribution: https://arcticoder.github.io/warp-bubble-optimizer/40eridani_energy_extended.png
816+
- Extended feasibility: https://arcticoder.github.io/warp-bubble-optimizer/40eridani_feasibility_extended.png
817+
818+
These are produced from the UQ runner and analysis steps in CI. See `.github/workflows/mission-validate.yml` and the notebook `notebooks/40eridani_analysis.ipynb` for details.
819+
820+
Goal alignment: positive-energy solitons and Natário zero-expansion geometry, advancing toward a 2063 demonstration mission profile.
821+
822+
## Contribute
823+
824+
We welcome collaboration on hardware scaling and theoretical integration:
825+
826+
- Hardware: laser–coil synchronization, plasma chamber design, envelope tracking
827+
- Theory: LQG corrections with sinc(πμ), Natário zero-expansion, positive-energy soliton profiles
828+
829+
Start here:
830+
831+
- Read CONTRIBUTING.md
832+
- Fork the repo, create a feature branch, add tests (pytest), and open a PR
833+
834+
Focus areas that need help now:
835+
836+
- Device facades and experiment plans for 2035–2050 prototypes
837+
- UQ extensions and CI artifact dashboards
838+
- Cross-repo schema consumers for mission/perf analytics
839+
774840
## Testing and CI
775841

776842
- Local quick run: use the lightweight tests and filters already configured in `pytest.ini` and `conftest.py`.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import dataclass
4+
5+
from .device_facade import DeviceFacade
6+
7+
8+
@dataclass
9+
class ExperimentPlan:
10+
laser_power: float
11+
coil_freq: float
12+
plasma_density: float
13+
r_shell: float
14+
width: float
15+
16+
def generate_plan(self) -> dict:
17+
return {
18+
'laser_power': self.laser_power,
19+
'coil_freq': self.coil_freq,
20+
'plasma_params': {
21+
'n0': self.plasma_density,
22+
'R': self.r_shell,
23+
'width': self.width,
24+
}
25+
}
26+
27+
def validate_plan(self, facade: DeviceFacade) -> bool:
28+
ok = facade.initialize_coil(self.laser_power)
29+
_ = facade.set_laser_frequency(self.coil_freq)
30+
_ = facade.set_plasma_density(self.plasma_density, self.r_shell, self.width)
31+
state = facade.read_field_state()
32+
return bool(ok and state.get('error', 1.0) < 0.45)

tests/test_impulse_vnv.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,20 @@ def test_rotational_performance_guard():
299299
dt_ms = (time.perf_counter() - t0) * 1000
300300
assert dt_ms < 300.0
301301

302+
def test_packaged_schema_access():
303+
import json
304+
from importlib import resources
305+
# Mission schema
306+
with resources.files('warp_bubble_optimizer').joinpath('schemas/impulse.mission.v1.json').open('rb') as f:
307+
mission_schema = json.load(f)
308+
# Check top-level identity
309+
assert mission_schema.get('$id', '').endswith('/impulse.mission.v1.json')
310+
# Perf schema
311+
with resources.files('warp_bubble_optimizer').joinpath('schemas/perf.csv.schema.json').open('rb') as f:
312+
perf_schema = json.load(f)
313+
required = set(perf_schema.get('required', []))
314+
assert 'segment_index' in required and 'segment_energy' in required
315+
302316

303317
def test_json_schema_file_validation_if_available(tmp_path):
304318
try:

tests/test_warp_generator.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
plasma_density,
1111
)
1212
from src.supraluminal_prototype.device_facade import DeviceFacade
13+
from src.supraluminal_prototype.experiment_plan import ExperimentPlan
1314
from impulse import IntegratedImpulseController, ImpulseEngineConfig, MissionWaypoint
1415
from src.simulation.simulate_vector_impulse import Vector3D
1516
from simulate_rotation import Quaternion
@@ -66,3 +67,11 @@ def test_mission_envelope_integration():
6667
assert synced_freq > 1e15
6768
state = dev.read_field_state()
6869
assert state['error'] < 0.45
70+
71+
72+
def test_experiment_plan():
73+
dev = DeviceFacade()
74+
plan = ExperimentPlan(laser_power=1.0, coil_freq=1e15, plasma_density=1e20, r_shell=0.5, width=0.1)
75+
cfg = plan.generate_plan()
76+
assert isinstance(cfg, dict) and cfg.get('laser_power') == 1.0
77+
assert plan.validate_plan(dev) is True

0 commit comments

Comments
 (0)