Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
7506585
Add configuration for giant-impact accretion
timlichtenberg Jul 22, 2026
721a99d
Add the accretion module and its impact timeline
timlichtenberg Jul 22, 2026
fb7eab1
Ignore a local Morrigan checkout
timlichtenberg Jul 22, 2026
7e766c3
Allow a body to shed atmosphere between impacts
timlichtenberg Jul 23, 2026
2b1879e
Land the timestep exactly on each scheduled impact
timlichtenberg Jul 23, 2026
1a0b7ba
Apply a giant impact's mass and orbit change during the run
timlichtenberg Jul 23, 2026
d249874
Re-melt the mantle to a molten state at each impact
timlichtenberg Jul 23, 2026
780d27a
Make the giant-impact re-melt survive and stay consistent
timlichtenberg Jul 23, 2026
4bcc589
Deliver an impactor's volatiles into the planet at each impact
timlichtenberg Jul 23, 2026
93d280f
Conserve the planet's volatiles across an impact's mass growth
timlichtenberg Jul 24, 2026
b038b10
Account the giant-impact re-melt heat in the energy budget
timlichtenberg Jul 24, 2026
ea93d1c
Strip part of the atmosphere at each giant impact
timlichtenberg Jul 24, 2026
230b065
Harden the impact accounting against thin-atmosphere and drift cases
timlichtenberg Jul 24, 2026
d35fe8b
Let impactors carry the planet's formation volatile abundances
timlichtenberg Jul 24, 2026
adc8bcf
Compute impact atmosphere loss with the ZEPHYRUS erosion law
timlichtenberg Jul 24, 2026
0172c2a
Require the fwl-zephyrus release that provides the collision law
timlichtenberg Jul 24, 2026
f66d7d2
Install Morrigan from a pinned commit like the other optional modules
timlichtenberg Jul 25, 2026
bffb273
Correct the pre-run impact behaviour in the time_offset description
timlichtenberg Jul 25, 2026
f991e5c
Depend on the published fwl-morrigan release instead of a commit
timlichtenberg Jul 25, 2026
0ab04b4
Guard the giant-impact re-melt against unphysical heat
timlichtenberg Jul 26, 2026
6ccfeec
Add an analytical accretion module and rename the file-driven one
timlichtenberg Jul 26, 2026
1b628c2
Correct the impact accounting and the new module's scaling limits
timlichtenberg Jul 26, 2026
70b2ce1
Apply an impact's orbit change to both elements, not just the semi-ma…
timlichtenberg Jul 26, 2026
399da78
Scope the helpfile backfill and cover the fixes that had no tests
timlichtenberg Jul 26, 2026
5652571
Require the giant-impact release that reports the pre-impact eccentri…
timlichtenberg Jul 26, 2026
7ceec24
Show accretion in the overview figures and carry the domain palette
timlichtenberg Jul 26, 2026
40004af
Show the accretion step in the architecture diagram
timlichtenberg Jul 26, 2026
fad73eb
Document the accretion module and clear the figure overlaps
timlichtenberg Jul 26, 2026
f6a822a
Require the Morrigan release that ships the coupling documentation
timlichtenberg Jul 26, 2026
28f6568
Merge branch 'main' into tl/accretion-morrigan-coupling
timlichtenberg Jul 26, 2026
eb74032
Drop redundant local imports from the accretion and interior tests
timlichtenberg Jul 27, 2026
6e4a191
Keep a resumed accretion run consistent with the impacts it applied
timlichtenberg Jul 28, 2026
5d4ce1c
Sharpen the assertions in the accretion tests
timlichtenberg Jul 28, 2026
26e2fb7
Cover the loop condition that drops an impact step's snapshot
timlichtenberg Jul 29, 2026
6943e72
Test that a run stopped on an impact resumes from before it
timlichtenberg Jul 29, 2026
d62006f
Keep a run going when the interior stops on a phase-change event
timlichtenberg Jul 29, 2026
4337d41
Match a resumed row to the snapshot that was written for it
timlichtenberg Jul 29, 2026
1e400ad
Cover the SPIDER half of the resume snapshot match
timlichtenberg Jul 29, 2026
38be269
Start the accretion resume test from a condition it can afford
timlichtenberg Jul 29, 2026
7bbae21
Name the front when the interior stalls on CVODE
timlichtenberg Jul 30, 2026
e1ec189
Take the domain colours from the theme stylesheet
timlichtenberg Jul 30, 2026
56a9d6b
Make the front-page buttons visible in the dark scheme
timlichtenberg Jul 30, 2026
396b2a5
Merge main into the accretion branch
timlichtenberg Jul 31, 2026
3885156
Let an impact re-wet a planet that had run dry
timlichtenberg Jul 31, 2026
d9365f0
Merge main into the accretion branch
timlichtenberg Jul 31, 2026
ab2eb0f
Merge main into the accretion branch
timlichtenberg Aug 1, 2026
116cc2b
Refuse accretion on the boundary interior, and test the two step caps…
timlichtenberg Aug 1, 2026
dc3977b
Merge main and record the two accretion columns into the golden traje…
timlichtenberg Aug 1, 2026
6984a0a
Take the rock-forming elements as a complement rather than a constant
timlichtenberg Aug 1, 2026
f859172
Pin the impact heat against a closed-form integral
timlichtenberg Aug 3, 2026
28162bc
Merge remote-tracking branch 'origin/main' into tl/accretion-morrigan…
timlichtenberg Aug 3, 2026
f21ac75
Record the trajectory again for the accretion columns
timlichtenberg Aug 3, 2026
e54115d
Refuse an impactor that is more volatile than it has mass
timlichtenberg Aug 3, 2026
c8bc763
Let the rock remainder tolerate closure rounding
timlichtenberg Aug 3, 2026
803be0a
Keep the interior solver on the planet an impact just made
timlichtenberg Aug 5, 2026
9c7b64d
Check the mesh against the factory just before the solve
timlichtenberg Aug 5, 2026
cb2f3fb
Clear the JAX factory when a rebuild of it fails
timlichtenberg Aug 6, 2026
9d829c2
Read the interior mesh on every solve, not once
timlichtenberg Aug 6, 2026
4c4689a
Install the JAX factory last, so a diagnostic cannot undo it
timlichtenberg Aug 6, 2026
00ca73b
Reload the EOS tables when they are regenerated
timlichtenberg Aug 6, 2026
8fb9540
Point the solver at the current tables before each solve
timlichtenberg Aug 6, 2026
38ec624
Refresh the tables before reset and test the reload wiring
timlichtenberg Aug 8, 2026
0be0464
Bound the time step that lands on a coarse-phase giant impact
timlichtenberg Aug 23, 2026
4f0bcd2
Merge origin/main into tl/accretion-morrigan-coupling
timlichtenberg Aug 30, 2026
32c8f7f
Backfill step_dE_impact_J on resume instead of blocking it
timlichtenberg Aug 30, 2026
bdf2056
Cover step_dE_impact_J in the schema-drift resume test
timlichtenberg Aug 30, 2026
f90af30
Document both zero-fill mechanisms for RESUMABLE_ZERO_FILL_KEYS
timlichtenberg Aug 30, 2026
f7d0fe3
Cover both zero-fill mechanisms in the resume test docstring
timlichtenberg Aug 30, 2026
b772033
Finish the two-mechanism zero-fill wording in coupler.py
timlichtenberg Aug 30, 2026
e9b8df8
Fix stale cumulative-only framing in state-vs-zero-fill test docstring
timlichtenberg Aug 30, 2026
dcabf8c
Distinguish lossless and lossy zero-fill in the resume docstring
timlichtenberg Aug 30, 2026
4507f50
Point resume test docstrings at the zero-fill explanation
timlichtenberg Aug 30, 2026
7988271
Drop the accretion loss-report claim from the resume docstring
timlichtenberg Aug 30, 2026
e837759
Merge origin/main into tl/accretion-morrigan-coupling
timlichtenberg Sep 10, 2026
d6e63c0
Apply ruff formatting after the main merge
timlichtenberg Sep 10, 2026
ca1a17a
Cite the Kegerreis et al. 2020 giant-impact erosion scaling law in th…
timlichtenberg Sep 10, 2026
7e2ace3
Correct the golden_run.tsv header count after the main merge
timlichtenberg Sep 10, 2026
93edd63
Reconcile the CVODE retry ladder with main's step-budget stall fix
timlichtenberg Sep 10, 2026
360d0b0
Fix retry-ladder test fixtures broken by the CVODE reconcile merge
timlichtenberg Sep 10, 2026
03ad107
Add coverage for the giant-impact exemption on a non-finite T_core
timlichtenberg Sep 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,14 @@ jobs:
files: >-
tests/integration/test_slow_aragog_calliope.py
tests/integration/test_slow_aragog_atmodeller.py
tests/integration/test_slow_accretion_resume.py
- shard: aragog
tier: critical
os: macos-latest
files: >-
tests/integration/test_slow_aragog_calliope.py
tests/integration/test_slow_aragog_atmodeller.py
tests/integration/test_slow_accretion_resume.py
# ---- shard: zalmoxis-dummy (real Zalmoxis + dummy
# everything else; Linux-only because the test is
# skipif(darwin) on macOS) ----
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ Love.jl/
BOREAS
boreas
Boreas
morrigan
Morrigan
MORRIGAN

# misc
######
Expand Down Expand Up @@ -335,3 +338,6 @@ src/proteus/_version.py
# Local scratch directories (not part of the project)
/.playwright-mcp/
/platon/

# Diagnostic dumps written by `proteus update` into the repo root.
/proteus_update_*.log
2 changes: 1 addition & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ representative at an online or offline event.

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
contact@formingworlds.space.
dev@proteus-framework.org.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
Expand Down
2 changes: 1 addition & 1 deletion docs/Community/CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ representative at an online or offline event.

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
contact@formingworlds.space.
dev@proteus-framework.org.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
Expand Down
1 change: 1 addition & 0 deletions docs/Explanations/code_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ coupled planetary evolution simulation:
- [`atmos_chem/`](https://github.com/FormingWorlds/PROTEUS/tree/main/src/proteus/atmos_chem): atmospheric photochemistry (VULCAN, dummy)
- [`escape/`](https://github.com/FormingWorlds/PROTEUS/tree/main/src/proteus/escape): atmospheric mass loss (ZEPHYRUS, dummy)
- [`outgas/`](https://github.com/FormingWorlds/PROTEUS/tree/main/src/proteus/outgas): volatile partitioning (CALLIOPE, atmodeller, dummy)
- [`accretion/`](https://github.com/FormingWorlds/PROTEUS/tree/main/src/proteus/accretion): protoplanet growth by giant impacts (Morrigan, timeline, dummy)
- [`orbit/`](https://github.com/FormingWorlds/PROTEUS/tree/main/src/proteus/orbit): orbital evolution and tides (Obliqua/LovePy, dummy)
- [`star/`](https://github.com/FormingWorlds/PROTEUS/tree/main/src/proteus/star): stellar evolution and spectra (MORS, dummy)

Expand Down
31 changes: 21 additions & 10 deletions docs/Explanations/coupling_loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,47 +42,58 @@ upstream modules.
melt fraction, and heat flux using the chosen solver (Aragog, SPIDER,
boundary, or dummy). Advances simulation time by the interior timestep.

2. **Structure update** (`update_structure_from_interior`): If Zalmoxis is
2. **Giant impacts** (`apply_impact`): Applies every impact whose time falls
within the step just taken. The impactor's rock is added to the planet and
the interior structure is re-solved at the new mass, its volatiles are
delivered while part of the target's atmosphere is stripped, the mantle is
re-melted by re-applying the run's temperature-mode initial condition, and
the orbit takes the impact's change in semi-major axis and eccentricity.
How molten the re-melt leaves the mantle follows that initial condition:
only `planet.temperature_mode = "liquidus_super"` is fully molten for any
planet mass and melting curve. Runs only when an accretion module is
configured and an impact is due.

3. **Structure update** (`update_structure_from_interior`): If Zalmoxis is
active and a structure update is triggered (by elapsed time, melt fraction
change, or temperature change exceeding configured thresholds), recomputes
the hydrostatic density profile and planet radius.

3. **Orbit and tides** (`run_orbit`): Updates orbital elements (semi-major
4. **Orbit and tides** (`run_orbit`): Updates orbital elements (semi-major
axis, eccentricity) and computes tidal heating rates. Tidal power is
distributed radially and passed to the interior module for the next
iteration.

4. **Stellar evolution** (`update_stellar_quantities`): Interpolates the
5. **Stellar evolution** (`update_stellar_quantities`): Interpolates the
stellar mass, radius, effective temperature, and luminosity from
pre-computed evolutionary tracks at the current stellar age. Recomputes
the instellation flux and XUV flux. The stellar spectrum is updated on a
separate, longer cadence controlled by `params.dt.starspec`.

5. **Atmospheric escape** (`run_escape`): Computes mass loss rates for each
6. **Atmospheric escape** (`run_escape`): Computes mass loss rates for each
element (H, C, N, S, O) based on the XUV flux, planet mass, and current
atmospheric composition. Updates element inventories by debiting the
escaped mass. Only active after the initialisation stage.

6. **Outgassing** (`run_outgassing`): Given the updated element inventories,
7. **Outgassing** (`run_outgassing`): Given the updated element inventories,
mantle temperature, and melt fraction, computes the thermodynamic
equilibrium partitioning of volatiles between atmosphere, melt, and solid.
Writes partial pressures, mixing ratios, and atmospheric mass to `hf_row`.
Also calls `update_planet_mass` and `assert_mass_conservation` to verify
the whole-planet mass budget.

7. **Atmosphere climate** (`run_atmosphere`): Solves the radiative-convective
8. **Atmosphere climate** (`run_atmosphere`): Solves the radiative-convective
structure of the atmosphere using the chosen backend (AGNI, JANUS, or
dummy). Takes the interior heat flux and atmospheric composition as input;
returns the surface temperature, outgoing longwave radiation, and Bond
albedo.

8. **Atmospheric chemistry** (`run_chemistry`): If configured for online mode,
9. **Atmospheric chemistry** (`run_chemistry`): If configured for online mode,
runs photochemical kinetics (VULCAN) to compute steady-state mixing ratios.
Most configurations skip this step or run it offline after the simulation.

9. **Housekeeping**: Updates iteration counters, checks convergence criteria,
writes the helpfile row to `hf_all`, generates plots and archives if
scheduled.
10. **Housekeeping**: Updates iteration counters, checks convergence criteria,
writes the helpfile row to `hf_all`, generates plots and archives if
scheduled.

## Initialisation stage

Expand Down
22 changes: 20 additions & 2 deletions docs/Explanations/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ atmosphere), enabling hierarchical model intercomparison.
| Escape | [ZEPHYRUS](https://github.com/FormingWorlds/ZEPHYRUS), dummy | Atmospheric escape |
| Outgassing | [CALLIOPE](https://proteus-framework.org/CALLIOPE/), [atmodeller](https://github.com/djbower/atmodeller), dummy | Volatile exchange between interior and atmosphere |
| Orbit | [Obliqua](https://github.com/FormingWorlds/Obliqua), dummy | Orbital evolution and tidal heating |
| Accretion | [Morrigan](https://proteus-framework.org/Morrigan/), timeline, dummy | Protoplanet growth by giant impacts |
| Observations | [petitRADTRANS](https://petitradtrans.readthedocs.io/), none | Synthetic transit and eclipse spectra |

Each module is maintained in its own repository and can be used as a standalone package outside of PROTEUS. The following sections describe each module's physical role and how PROTEUS couples to it.
Expand Down Expand Up @@ -195,6 +196,18 @@ Some notable consequences of step 3:

Config section: `[orbit]`. Reference: [Star and orbit configuration](../Reference/config/star_orbit.md).

## Accretion: Morrigan

The accretion module supplies the giant impacts a planet experiences after the disk disperses, and PROTEUS applies each one to the planet it is evolving.

**[Morrigan](https://proteus-framework.org/Morrigan/)** (Python) follows a system of planetary embryos through the secular eccentricity oscillations, orbit crossings, scatterings, ejections and giant impacts by which they accrete, until the system settles into a Hill-stable configuration. It implements the semi-analytical Monte Carlo model of Kimura et al. (2025) [^cite-kimura2025], which predicts when a system goes unstable and resolves each instability with prescriptions calibrated against N-body simulations, rather than integrating the orbits. That makes one system cheap enough to run inside a coupled framework, at the cost of any single history being a statistical realisation rather than a trajectory: ensemble statistics are the meaningful comparison. PROTEUS follows one survivor of that system, chosen by the configured selector, and takes its impact history.

Each impact is applied at the timestep it falls in. The impactor's rock grows the planet and the interior structure is re-solved at the new mass, so radius, gravity and the core-mantle split follow the growth. The impactor's volatiles are delivered while the same collision fraction strips the target's atmosphere and the impactor's own, so a small impactor striking a heavily-clothed planet can leave it lighter than before. The mantle is re-melted by re-applying the run's temperature-mode initial condition, and the orbit takes the collision's change in semi-major axis and eccentricity, clamped to a bound orbit.

Two further implementations take an impact history rather than derive one. `timeline` replays a table of impacts from a file, which reproduces a published history or drives PROTEUS from one computed elsewhere. `dummy` builds a history from scaling laws: the planet approaches an asymptotic mass exponentially, impacts are evenly spaced in time, and each delivers the mass the law accretes over its interval, so the increments decay and the largest impact is the first. With no accretion module selected the impact list is empty and the planet's mass is set by its initial condition alone.

Config section: `[accretion]`. Reference: [Accretion configuration](../Reference/config/accretion.md).

## Synthetic observations: petitRADTRANS

**[petitRADTRANS](https://petitradtrans.readthedocs.io/)** (Python) is a radiative transfer code for computing exoplanet transmission and emission spectra. PROTEUS uses petitRADTRANS as a forward model to synthesise what an observer would measure given the simulated atmospheric state.
Expand Down Expand Up @@ -241,9 +254,12 @@ architecture and for quick parameter exploration.
| Escape | Constant bulk mass loss rate (user-specified kg/s), distributed proportionally across elements |
| Outgassing | Melt-fraction-dependent volatile partitioning with fixed stoichiometry, no equilibrium chemistry |
| Orbit | Fixed semi-major axis and eccentricity; configurable parameterised tidal heating |
| Accretion | Exponential approach to an asymptotic mass, delivered as evenly spaced impacts; Noack & Lasbleis (2020) [^cite-noack2020] radii and momentum-conserving mergers |

The [Quick start tutorial](../Tutorials/quick_start_dummy.md) runs PROTEUS
with all modules set to dummy.
The [Quick start tutorial](../Tutorials/quick_start_dummy.md) runs PROTEUS with
every physics module set to dummy. Accretion is left out of that configuration,
so the planet keeps the mass its initial condition gives it; add an
`[accretion]` section with `module = "dummy"` to let it grow.

---

Expand Down Expand Up @@ -296,3 +312,5 @@ Only the interior and star modules have an explicit notion of time-evolution. Al
[^cite-baraffe2015]: Baraffe, I., Homeier, D., Allard, F. & Chabrier, G., *[New evolutionary models for pre-main sequence and main sequence low-mass stars down to the hydrogen-burning limit](https://doi.org/10.1051/0004-6361/201425481)*, Astronomy & Astrophysics, 577, A42, 2015. [SciX](https://scixplorer.org/abs/2015A%26A...577A..42B/abstract).

[^cite-noack2020]: Noack, L. & Lasbleis, M., *[Parameterisations of interior properties of rocky planets](https://doi.org/10.1051/0004-6361/202037723)*, Astronomy & Astrophysics, 638, A129, 2020. [SciX](https://scixplorer.org/abs/2020A%26A...638A.129N/abstract).

[^cite-kimura2025]: Kimura, T., Hoshino, H., Kokubo, E., Matsumoto, Y. & Ikoma, M., *[Semi-analytical model for the dynamical evolution of planetary systems via giant impacts](https://doi.org/10.3847/1538-4357/ade992)*, The Astrophysical Journal, 989, 109, 2025.
1 change: 1 addition & 0 deletions docs/How-to/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ For topic-specific parameter guides, see the **configuration reference** pages:
- [Interior structure and energetics](../Reference/config/interior.md)
- [Atmosphere and chemistry](../Reference/config/atmosphere.md)
- [Escape and outgassing](../Reference/config/escape_outgas.md)
- [Accretion](../Reference/config/accretion.md)
- [Synthetic observations](../Reference/config/observe.md)

For worked examples, see the [Tutorials](../Tutorials/quick_start_dummy.md).
Expand Down
28 changes: 28 additions & 0 deletions docs/How-to/optionalmodules_installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,31 @@ bash tools/get_vulcan.sh
!!! warning "License"
VULCAN is distributed under the GPL-3.0 license; review its terms
before installing.

## Protoplanet accretion (Morrigan)

Morrigan is an optional giant-impact accretion module, selected with
`accretion.module = "morrigan"`. It evolves a system of planetary embryos
through orbital crossings and collisions and returns the impact history
that the coupled run replays. It is not required for a standard PROTEUS
run. Install it from PyPI:

```console
pip install "fwl-proteus[morrigan]"
```

For local development, install as an editable checkout instead:

```console
bash tools/get_morrigan.sh
```

An accretion run needs an interior module that can re-melt the mantle
after an impact. Aragog is the production choice; SPIDER is refused at
configuration load because it has no re-melt path.

Two accretion modules need no installation at all. `accretion.module =
"dummy"` builds an impact history from scaling laws, and `accretion.module
= "timeline"` replays one from a file, which is how a published or
externally computed impact history drives a run. Both apply the same
impact physics as the dynamical model.
13 changes: 7 additions & 6 deletions docs/How-to/update_module_pins.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module is distributed.
| Pin type | Where it lives in `pyproject.toml` | Pin value | Modules |
|----------|------------------------------------|-----------|---------|
| PyPI floor | `[project] dependencies` | Minimum version bound, e.g. `fwl-aragog>=26.05.13` | fwl-janus, fwl-mors, fwl-calliope, fwl-zephyrus, fwl-aragog, fwl-zalmoxis |
| PyPI floor (optional) | `[project.optional-dependencies]` | Minimum version bound on an optional backend | fwl-vulcan, atmodeller |
| PyPI floor (optional) | `[project.optional-dependencies]` | Minimum version bound on an optional backend | fwl-vulcan, atmodeller, fwl-morrigan |
| Git ref | `[tool.proteus.modules.<name>]` | Exact commit SHA, tag, or branch in a `ref` field | AGNI, SOCRATES, SPIDER, BOREAS, LovePy |

A third entry, PETSc, is pinned in `[tool.proteus.modules.petsc]` by the SHA-256
Expand Down Expand Up @@ -169,11 +169,12 @@ When in doubt, pin to a commit SHA. A branch pin is a deliberate choice to
follow upstream, not a default.

!!! info "Some modules deliberately have no git entry"
VULCAN, like fwl-aragog and fwl-zalmoxis, is a single-source PyPI package, so
it is pinned only by its floor in `[project.optional-dependencies]`. Its
setup script checks out the git tag matching that floor, so the editable
checkout and the published release cannot diverge. Do not add a second pin
for these in `[tool.proteus.modules]`.
VULCAN and Morrigan, like fwl-aragog and fwl-zalmoxis, are single-source
PyPI packages, so they are pinned only by their floor in
`[project.optional-dependencies]`. Their setup scripts check out the git tag
matching that floor, so the editable checkout and the published release
cannot diverge. Do not add a second pin for these in
`[tool.proteus.modules]`.

## Propagating the change to other developers

Expand Down
Loading
Loading