ADR 0024: Entwicklungswerkzeuge als eigenes Ökosystem-Paket (@small-world/tools)
Kontext & Problem
Die Kern-Engine verfolgt die Philosophie eines ultraleichten Kerns; Domänenspezifisches wandert in separate Workspace-Pakete (ADR 0014, ADR 0018, ADR 0021, ADR 0022). Aktuell liegen alle Editor-/Diagnose-Werkzeuge (Maker, MaterialStudio, Pixler, Xtractor, MapGenerator, der Forge-Fenstermanager) physisch unter packages/engine/src/tools/ — Teil des Kern-Pakets @small-world/engine —, obwohl eine ausgelieferte Spiel-Anwendung sie zur Laufzeit nie braucht.
Bundle-Größe ist dafür bereits über dynamische import()-Aufrufe plus einen bewusst unvollständigen Barrel-Export gelöst (tools/index.ts dokumentiert das explizit im Code-Kommentar). Das eigentliche Problem ist also nicht Bundle-Bloat, sondern Paket-/Abhängigkeitsgraph-Klarheit, der Install- und tsc-Kompilier-Footprint für Konsumenten, die nur die Engine wollen, und eine bereits an anderer Stelle dokumentierte Lücke: small-world/tools ist kein sauber auflösbarer Package-Export.
Der eigentliche Knoten: SmallWorld.ts (Kern) importiert selbst dynamisch aus ../tools/... (Forge + vier konkrete Tools), um bei config.enableInspector automatisch ein Dev-Overlay zu öffnen. Ein reiner Verzeichnis-Umzug würde daraus eine Abhängigkeit Kern → Tools-Paket machen — genau die Richtung, die ADR 0021 für Extras-Pakete ausdrücklich ausschließt ("kein Extras-Paket darf je @small-world/engine importieren … nie umgekehrt" gilt hier spiegelbildlich: der Kern darf nicht von einem extras-artigen Paket abhängen).
Entscheidung
- Neues Workspace-Paket
@small-world/toolsunterpackages/tools/, nach demselben Muster wiegeometry-extras/physics-extras/vfx-extras/gltf-extensions: hängt von@small-world/engineab, nie umgekehrt. - Reine Verschiebung (keine Verhaltensänderung) in dieses Paket:
tools/maker/(komplett inkl.docs/),tools/material-studio/,MaterialStudio.ts,Pixler.ts,Xtractor.ts,MapGenerator.ts,tools/forge/Forge.ts,ForgeWindow.ts,ForgeTheme.ts. - Im Kern bleibt bewusst:
forge/ForgeTool.ts(die Schnittstelle/der Erweiterungspunkt, schon heute barrel-exportiert) sowieprocgen/GridLevelBuilder.tsundIBLShaders.ts/ibl-gen.ts— das sind zur Laufzeit genutzte Engine-Features (z. B. YADs ASCII-Dungeon-Generierung überGridLevelBuilder), keine Entwicklungswerkzeuge, auch wenn sie organisatorisch im selbentools/-Ordner lagen. SmallWorld.tss hartkodierte Inspector-Verdrahtung (Forge +MapGenerator/Pixler/Xtractor/MaterialStudioautomatisch öffnen, wennenableInspector: true) wird ersatzlos aus dem Kern entfernt. Stattdessen exportiert@small-world/toolseine FunktionattachDevTools(app: SmallWorld): void, die genau das tut. Apps, die das In-Game-Overlay wollen, rufen sie selbst auf — das ist die einzige Möglichkeit, die Ein-Weg-Abhängigkeit sauber zu halten, ohne eine weiche/optionale Paketabhängigkeit im Kern zu erfinden.- Die vier
public/tools/*.html-Einstiegspunkte, die direkt aus dem Quellbaum importieren (maker.html,map-gen.html,pixler.html,pbr-gen.html), bekommen aktualisierte Importpfade aufpackages/tools/src/....
Erwogene Alternative (verworfen)
@small-world/tools als optionale Peer-Dependency von @small-world/engine führen und die Inspector-Verdrahtung in SmallWorld.ts per rein dynamischem import("@small-world/tools/...") (Paketname statt Relativpfad) beibehalten. Verworfen: das macht den Kern implizit abhängig von einem Paket, das seinerseits vom Kern abhängt — eine zyklische Paketbeziehung, nur zur Laufzeit statt zur Kompilierzeit versteckt. Das widerspricht der in ADR 0021 festgelegten strikten Ein-Weg-Regel und würde bei jedem künftigen Tool eine weitere unsichtbare Rückkopplung in den Kern schmuggeln.
Konsequenzen
@small-world/engines eigener Quellbaum verliert die komplette Tool-Implementierung (Maker- und MaterialStudio-Module, Pixler, Xtractor, MapGenerator, Forge) — kleinerer Install- undtsc-Footprint für reine Engine-Konsumenten.SmallWorldverliert die Kenntnis konkreter Tool-Klassen; sie kennt danach nur nochForgeTool(die Schnittstelle). Ob auch dieforge-Property und derKeyG-Toggle-Mechanismus in_onKeyDownmit auswandern oder als generischer Hook im Kern bleiben, ist bei der Umsetzung zu entscheiden.- Breaking Change: Jede bestehende App, die sich bisher auf
enableInspector: trueallein verlassen hat, um automatisch Forge + die vier Tools zu bekommen, muss beim Umsetzen auf den explizitenattachDevTools(app)-Aufruf umgestellt werden. Das ist eine bewusste, nicht stillschweigende Migration. - Löst die bereits dokumentierte
small-world/tools-Subpath-Lücke:@small-world/toolswird ein echtes, eigenständig auflösbares Paket mit eigenempackage.json/exports. - Folgeaufwand bei Umsetzung: die vier
public/tools/*.html-Importpfade,packages/engine/src/tools/index.ts-Barrel entsprechend kürzen, neuepackages/tools/package.json+tests/-Verzeichnis (bestehende Maker-/MaterialStudio-Tests wandern mit).