Build pipeline
build_starwind.py is the only supported build entry point. The modern project
has no Solo, Standalone, or TSI content modes. Definitive Starwind has one
approved source corpus and one deterministic build graph.
Entry point
./build_starwind.py --strict
Useful operational flags may control cleanup or retained work artifacts, but they do not change which Starwind content belongs to the product.
Fixed source graph
The canonical merge order is:
Bing's Race Pack -> Starwind Enhanced
Enhanced -> StarwindRemasteredPatch
PlanExp -> StarwindRemasteredPatch
Alt Start -> StarwindRemasteredPatch
CPP -> StarwindRemasteredPatch
Naboo -> StarwindRemasteredPatch
Patch -> StarwindRemasteredV1.15
PartyHats -> canonical Definitive merge
canonical merge -> Minimal -> addVanillaRefs -> masterless monolith
masterless monolith -> Star_Data + Starwind
The merge_to_master command takes <plugin> <master> and writes the merged
result into the second file. The arrows above describe the effective flow, not
an abstract dependency graph.
Stages
1. Compile canonical JSON sources
All approved plugins/*.json sources are converted to temporary TES3
ESM/ESP files with tes3conv under:
.swbuild/definitive/work/
Canonical JSON inputs are never edited by compilation. tes3cmd surgery is
performed against staged work copies unless a cleanup has explicitly been
promoted to a canonical source change.
2. Parent-aware source dialogue hygiene
Before the canonical merge, the source dialogue is audited against the parent state it actually inherits from. This prevents a Patch record from being misclassified by comparing it only to Bethesda masters when it is actually an override of V1.15.
See Dialogue canonicalization and the Historical cleanup ledger.
3. Main-quest preservation: pre-preprocess check
A reviewed set of main-quest DIAL/NPC/SCPT anchors and a live
SW_ShipQuester cell reference are asserted before any Definitive source
surgery runs.
This guard exists specifically because the old multiplayer build intentionally removed pieces of Starwind's main quest. Definitive Edition must never inherit those destructive server-only edits by accident.
4. Definitive preprocessing
Only reviewed source-cleaning and integration operations run. Historical TSI multiplayer policy is not reused as a convenience layer.
Before the canonical merge, the build removes a manually audited set of 25
non-playable CLAS records from the staged Bethesda inputs and the staged
V1.15 override input. The list is limited to classes with zero NPC, dialogue,
and script references; it does not perform general class reachability pruning.
The canonical vanilla JSON sources remain unchanged.
The build explicitly does not apply the old TSI gold/Kolto substitutions,
main-quest instance removals, SW_ShipQuester removal, Courte server cleanup,
or other server-only reference surgery.
See Source corpus & preprocessing.
5. Main-quest preservation: post-preprocess check
The exact active staged source files are checked again. tes3cmd backup files
such as ~1.esm are excluded so a backup copy cannot falsely satisfy a quest
anchor that preprocessing deleted from the real input.
6. Canonical merge
Bing is first folded into Enhanced. Enhanced, PlanExp, Alt Start, CPP, and Naboo are folded into the Patch. Patch is folded into V1.15. PartyHats is then folded into the canonical merged result.
StarwindMPRecords and StarwindVvardenfell never enter this graph.
7. Equipment enchantment normalization
Otherwise-unenchanted clothing, armor, and weapons receive enchantment
capacity 375.
This is a Definitive Edition design policy, not a compatibility hack. The project deliberately favors equipment freedom and player personalization over preserving Morrowind's original item-enchantment balance.
8. Main-quest preservation: post-merge check
The canonical merged artifact is checked before master decoupling.
9. Fold into Minimal
The canonical Starwind merge is merged into the deliberately tiny Minimal
plugin. Minimal provides the TES3 master context required by the historical
merge/decoupling path without contributing a second body of world/dialogue
content.
10. Standalone-only vanilla surgery
The staged Bethesda masters are adjusted only where Definitive Starwind has a reviewed reason not to see certain inherited data. The canonical Bethesda JSON files remain untouched.
The best-known example is the exact 53-INFO vanilla faction-dialogue prune. See Master decoupling.
11. Recursive master decoupling
addVanillaRefs recursively imports required Bethesda records, reconstructs
and prunes dialogue, performs a second dependency-closure pass after dialogue
materialization, and removes the Bethesda masters.
12. Final masterless cleanup
Deletion tombstones are removed only after their inherited deletion semantics have done their job. Exact duplicate physical MGEFs may be deduplicated, but MGEF/SKIL/GMST are never reachability-pruned.
13. Main-quest preservation: final monolith check
The final Starwind-Definitive.omwaddon is checked once more.
14. Closure and dialogue validation
The monolith must have no masters, no unresolved hard references, and exact OpenMW-effective dialogue. In strict mode, physical dialogue order and serialized links must also be exact.
15. Data/content split
The validated monolith is partitioned into Star_Data.omwaddon and
Starwind.omwaddon, then the serialized pair is independently validated to
reconstruct the monolith exactly.
Generated tree
.swbuild/definitive/
├── work/
│ ├── compiled source plugins
│ ├── staged Bethesda masters
│ └── decoupleLog.txt
├── out/
│ ├── Starwind-Definitive.omwaddon
│ ├── Star_Data.omwaddon
│ └── Starwind.omwaddon
├── reports/
│ ├── main-quest-preservation.json
│ ├── Starwind-definitive-dialogue-source-hygiene.json
│ ├── Starwind-Definitive-dialogue-chain-audit.json
│ ├── starwind-split-report.json
│ └── late-actor-provenance.json
└── build-manifest.json
The closure helper currently writes its closure report under the shared
.swbuild/reports/ path; the manifest records the exact path used by the
current build.
Build outputs
Starwind-Definitive.omwaddon is an internal canonical oracle. The release
pair is:
Star_Data.omwaddon
Starwind.omwaddon
The content plugin declares Star_Data.omwaddon as its sole master.
Invariants
The builder is considered correct only if changing internal implementation leaves these externally observable invariants intact:
- approved source corpus is fixed;
- no old TSI server-only surgery executes;
- main quest remains present at every checkpoint;
- monolith is masterless;
- hard closure is complete;
- OpenMW dialogue is exact;
- split reconstructs monolith exactly;
- Data never depends on content.