Public API tier table
declarative-hex-worlds publishes one umbrella entry plus a wide
set of subpath exports. Every subpath stays supported through 1.0 — this
is an asset-bundled library where mod authors, custom-renderer builders, and
data-inspection tooling all have legitimate reasons to reach internals.
What changes between tiers is the stability contract, not the availability. Pick the tier that matches your tolerance for breakage; the tooling and TSDoc tags tell you which tier a symbol belongs to.
Tier 1 — Stable
Section titled “Tier 1 — Stable”Semver-strict. Breaking changes only on major versions, always with a migration guide.
| Subpath | Purpose |
|---|---|
. (umbrella) |
Default entry. Re-exports the consumer-facing surface from every tier-1 sub-package. |
./react |
React bindings. First-class (NOT peer-gated). Hooks, providers, components. |
./three |
Three.js bindings. First-class (NOT peer-gated). Loaders, disposers, scene helpers. |
./cli |
CLI entry (also installed as the declarative-hex-worlds bin). |
./manifest/schema |
MedievalHexagonManifest shape + validators. |
./manifest/free |
Pre-baked FREE-edition manifest metadata. |
./scenario |
GameboardScenario, blueprint/recipe/catalog/registry. |
./blueprint |
GameboardBlueprintOptions and procedural board generation. |
./gameboard |
Board lifecycle, occupancy, navigation. |
./recipe |
Recipe DSL. |
./coverage |
Release-readiness coverage ledger surface for build/review tooling, not runtime ECS adapter glue. |
./compatibility |
Manifest/version compatibility helpers. |
./errors |
GameboardError + typed subclasses (Epic D2). |
./traits |
Single trait umbrella (all trait() declarations). |
./types |
Shared primitive types + branded IDs (HexKey, ActorId, etc.). |
./examples/*.json |
Bundled example scenario JSON. |
TSDoc tag: @public.
Branded ID migration status
Section titled “Branded ID migration status”The ./types subpath exports branded ID aliases and brand* helpers, but
branded IDs are NOT yet enforced across the runtime. Public JSON, manifest,
CLI, and ECS-facing shapes still use plain strings unless a domain row below
states that enforcement has landed. Treat the aliases as opt-in compile-time
helpers until the relevant domain moves to enforced.
| Domain(s) | Brands tracked | Current status |
|---|---|---|
./types |
HexKey, ActorId, TileId, PieceId, PlacementId, ScenarioId, QuestId, ObjectiveId, PatrolRouteId, AssetId |
Registry exported; brand* helpers are stable and available to consumers. |
./coordinates, ./grid, ./layout, ./gameboard |
HexKey, TileId |
Not yet enforced; public APIs still accept coordinate objects and plain string IDs. |
./scenario, ./recipe, ./blueprint, ./simulation, ./pieces |
ScenarioId, PieceId, PlacementId, TileId, AssetId |
Not yet enforced; scenario JSON and generated plans keep wire-compatible string fields. |
./actors, ./movement, ./patrol, ./quests |
ActorId, PatrolRouteId, QuestId, ObjectiveId |
Not yet enforced; ECS traits, commands, and query helpers still expose string-compatible IDs. |
./manifest/schema, ./manifest/free, ./ingest, ./runtime, ./react, ./three |
AssetId |
Not yet enforced; asset IDs remain manifest and URL-facing strings. |
./cli, ./interop, ./compatibility, ./coverage |
Pass-through IDs only | Not yet enforced; these surfaces preserve external wire formats and report existing domain values. |
Tier 2 — Supported-for-extension
Section titled “Tier 2 — Supported-for-extension”Semver-strict for what’s documented, but the surface contract is smaller than tier 1. Mod authors and custom-renderer consumers can depend on these; breaking changes still require a major + migration guide but the “what’s breaking” frame may be narrower (a specific function signature changing rather than the whole module shape).
| Subpath | Purpose |
|---|---|
./koota |
World bootstrap, trait sets, query patterns. |
./runtime |
High-level runtime composition. |
./actors |
Actor surface + queries. |
./movement |
Movement-agent surface. |
./patrol |
Patrol-route surface. |
./quests |
Quest surface. |
./pieces |
Piece declarations + placement helpers. |
./projection |
World-space placement projection. |
./layout |
Seeded board layout generation. |
./grid |
Honeycomb-grid wrappers + hex algebra. |
./coordinates |
Hex coordinate algebra (umbrella over grid/projection/layout). |
./validation |
Plan-level validators. |
./rules |
Rule definitions + evaluation. |
TSDoc tag: @public (no distinct tag — tier 2 is documented here in the
table, not on every symbol).
Tier 3 — Internal-but-exposed
Section titled “Tier 3 — Internal-but-exposed”Semver-permissive: minor versions may change these surfaces in non-trivial ways. Consumers who pin tier-3 imports accept this tradeoff. Useful for very-deep modding, debugging, and tools that need to inspect or hook the implementation.
| Subpath | Purpose |
|---|---|
./commands |
Internal command-factory plumbing. |
./selectors |
Per-render shape pickers used by React/Three bindings. |
./systems |
Tickable system functions. |
./world-rules |
Runtime rule-evaluation system. |
./rule-types |
Rule typed shapes (re-exported from ./rules — prefer that). |
./interop |
Runtime ECS adapter glue and schema migrations; release-readiness coverage is the separate stable ./coverage surface. |
./ingest |
Source-tree walker + manifest emission (precursor to bootstrap). |
./registry |
Tile/piece registries (re-exported from ./scenario). |
./catalog |
KayKit asset catalog (re-exported from ./scenario). |
TSDoc tag: @internal (still exported, still typed, still tested — just
flagged so consumers see the support tier inline).
Why the three tiers?
Section titled “Why the three tiers?”Phase 1’s architecture review (F1) noted that the 37+ subpath exports permanently pin every internal module as a semver surface point. The original recommendation was to demote ~10 subpaths and force everything through the umbrella.
Per PRD §4 Epic D1 (re-scoped), that was rejected: this library bundles the FREE KayKit pack so consumers get a working game out-of-box, and the “out-of-box” promise extends to consumers who want to reach internals for legitimate reasons (custom renderers, modding, data inspection). The right tradeoff is documented tiering, not gated demotion.
If a tier-3 surface stabilizes (a custom-renderer mod has been depending
on ./selectors for two minor versions without breakage), it can be
promoted to tier 2 via a CHANGELOG note. The reverse (demoting a tier-1
surface) is a major-version event.
Trait identity invariant
Section titled “Trait identity invariant”Regardless of tier, every trait() declaration is exported from exactly
one module. tsup’s splitting: true keeps shared chunks stable so
that two consumers importing GameboardActor from different subpaths
(e.g. one via ./actors, another via the umbrella) get the SAME trait
identity — which is what koota’s useQuery reference-equality lookups
depend on.
Don’t try to “optimize” by re-declaring a trait somewhere else. Don’t fork the trait file into a “local” copy. The trait-identity test (Epic E4, pending) pins this.