# Mawu Studio: Creation Tools

Mawu Studio is where a player stops being a citizen of someone else's realm and
becomes a world-maker. It is the tiered creation funnel V7 promises — "build the
world, don't just play it" — spanning premium UE Editor authoring, an in-realm
builder you use while standing inside a running world, a no-code-to-code
scripting ladder, and AI-assisted generation, with every tool emitting the same
unit of currency: an **Ixchel layer** that composes into a realm on join. Where
the [Ixchel sandbox page](./ixchel-sandbox-and-modding.md) covers how untrusted
creator code is _run safely_, and the
[Abundantia page](./abundantia-creator-republic.md) covers how a finished realm
is _distributed and paid for_, this page covers the step between them: what a
creator actually _makes_, with what tools, and what comes out the other end.

It carries a particular burden of proof, because Mawu Studio is the V7 surface
most tempting to describe richly and ship thinly. So this page follows the code.
The strongest, automation-covered work is the **in-realm builder**
(`MawuBuilder` in `V7/ue/`) and the **realm-side geometry** it drives; the
scripting and AI-creation surfaces are real gates and compile-targets with
honestly-labelled seams; the asset-budget linter is shipped and tested; and the
heavy DCC asset pipeline is named-but-absent. For the full feature scope this
slots into, start at the hub: [../V7_features.md](../V7_features.md).

## What ships, honestly

The V7 monolith (features§"Mawu Studio — Creation Tools") describes a four-tier
funnel; the tree implements it unevenly, and it is worth stating the split up
front.

- **The in-realm builder is real C++ and automation-covered.** `MawuBuilder`'s
  `UMawuBuilderPlacementLibrary` (`MawuBuilderPlacement.h:155`) validates
  grab-and-place edits across eight operation kinds (block / voxel / CSG
  union·subtract·intersect / model / sculpt / UV-project), tracks desktop-gizmo
  vs. VR-grab parity, snaps to grid, bounds-checks placement, and publishes a
  validated `FMawuRealmLayer` — a genuine Ixchel layer with a content hash.
- **Builder operations drive real geometry, not just enum tags.** Every modeling
  op maps to a UE5 **Geometry Script** call inside
  `AMawuComposedRealmActor::BuildProceduralPrimitive`
  (`MawuComposedRealmActor.cpp:164`) — voxel solidify, mesh booleans, Perlin
  sculpt displacement, planar UV projection — producing real triangle/vertex
  counts and watertight solids, asserted by three V7 automation tests.
- **Scripting compiles to one canonical target — as a model.** Moremi lowers
  both a visual-logic graph and TypeScript to a shared canonical IR against one
  WASM compile target (`compile_mawu_studio_visual_logic_to_wasm` /
  `_typescript_to_wasm`), and a publish linter rejects a layer that references a
  missing asset. The compile step is a canonical-IR lowering and line parser,
  not a production TS→WASM toolchain; treat it as the typed contract, not a
  compiler.
- **AI-assisted creation is a real policy gate with a fail-loud backend.**
  `evaluateMawuStudioGenerationPolicy` (`mawu-studio-ai-creation.ts:274`)
  enforces Isis policy and Sophia grounding; `runMawuStudioAiCreation` returns
  `backend-not-configured` rather than fabricating an artifact when no real
  generation model is injected. The gate is genuine; the diffusion model is an
  injected seam.
- **The asset-budget linter is shipped and `[x]`.**
  `lint_mawu_studio_asset_budget` flags total and per-category byte overruns,
  naming offending assets largest-first, with an eval pinning a 17-vs-16-MiB
  overrun and a clean pass.
- **The web Studio is two pages.** `apps/oshun/web/src/app/mawu-studio/` ships
  `accessibility/` and `localization/` route shells over real evals; the full
  builder/browser web UI the monolith promises is product surface, not committed
  code.
- **The DCC asset pipeline is absent.** FBX/glTF/USD/Alembic import,
  photogrammetry/splat ingest, and Nanite/LOD auto-optimization (§14) have no
  code in `V7/ue` or any V7 library. Cite the in-realm builder for geometry, not
  an import pipeline.

## The creation tools

### The four-tier funnel

The product shape is a creation funnel from "make it cooler" to "modify the
Rayleigh-scattering coefficient": **UE Editor** authoring for premium worlds and
cinematics, the **in-realm builder** for in-context construction, **visual logic
→ TypeScript** for behaviour, and **AI-assisted** generation across the lot. The
funnel's organizing rule, inherited from the V5 creator suite and the V3 Lilith
Studio split, is that every tool emits an Ixchel layer and every layer passes
the same publish linter before it can ship — referential errors block publish
rather than surfacing as a runtime crash on some other player's machine.

### The in-realm builder

This is where the code is strongest, because in-context building has a sharp,
testable burden: an edit placed in a live world must be validated, snapped,
bounded, and turned into a composable layer. `FMawuBuilderPlacementRequest`
(`MawuBuilderPlacement.h:29`) is one edit — a `PrimitiveId`, a realm primitive
`Kind` (cube/plane/pillar/marker), an `EMawuBuilderOperationKind`
(`MawuBuilderPlacement.h:16`: `Block`, `Voxel`, `CsgUnion`/`CsgSubtract`/
`CsgIntersect`, `Model`, `Sculpt`, `UvProject`), the `EMawuBuilderInputSurface`
it was authored from (`DesktopGizmo` or `VrGrab`), a transform, extents, a grid
size, a placement bound, a colour, and a material role.

`EvaluatePlacement` (`MawuBuilderPlacement.cpp:163`) is the per-edit gate: it
rejects a missing id, a non-positive grid or bound, snaps each axis with
`FMath::GridSnap` when `bSnapToGrid` is set, runs the primitive's own `IsValid`,
and rejects anything beyond `MaxDistanceFromOriginCm` from the origin.
Crucially, it sets the emitted primitive's **realm** operation via
`MapBuilderOperationToRealm` — voxel, CSG, sculpt, and UV-project map to their
realm-geometry counterparts, while a plain `Block` and an imported `Model` map
to `None` (the legacy BasicShape path). That mapping is what makes a builder
edit _drive geometry_, not merely classify it, and it has its own automation
test (`V7.Mawu.Builder.GeometryOpsDriveRealmOperationKind`).

`PublishIxchelLayer` (`MawuBuilderPlacement.cpp:222`) is the layer gate. From a
`FMawuBuilderLayerDraft` (a realm id, an Ixchel layer id defaulting to
`ixchel.builder.draft`, an author account, a priority, and a list of placements)
it re-evaluates every placement, accumulates desktop/VR authoring counts, tracks
which operation families were exercised, builds a canonical payload, and stamps
a stable content hash (`StableBuilderContentHash` — a deterministic
FNV-1a-derived 256-bit digest emitted in the `sha256:` content-hash shape; the
authoritative cryptographic hashing happens server-side in the Ixchel content
store). It then enforces three optional coverage gates a serious realm can
require: `bRequireDesktopVrParity` (every edit reproducible on both input
surfaces), `bRequireBlockVoxelCsgCoverage`, and
`bRequireModelingSculptingUvCoverage`. The result is a validated
`FMawuRealmLayer` ready to compose — the same layer type a realm's lock file
pins.

What keeps the in-realm builder task `[ ]` despite this real code is the live
loop: there is no networked VR input device path and no publish-into-a-running-
session that other clients compose on join. The placement-and-publish library
and its geometry are real; the end-to-end "build inside a running realm and
watch it appear for everyone" flow is the integration target, consistent with
the intake-and-serve seam the Ixchel architecture page names.

### From a builder edit to real geometry

A placed primitive whose `OperationKind != None` is realised as a genuine UE5
`UDynamicMesh` by `AMawuComposedRealmActor::BuildProceduralPrimitive`
(`MawuComposedRealmActor.cpp:164`). It appends a subdivided base box
(`UGeometryScriptLibrary_MeshPrimitiveFunctions::AppendBox`, 4×4×4 so
deformations have vertices to move) and then dispatches on the op: `Voxel` runs
`ApplyMeshSolidify` (a sparse-voxel remesh); the three CSG kinds build an
overlapping tool box and run `ApplyMeshBoolean` with
Union/Subtract/Intersection; `Sculpt` runs `ApplyPerlinNoiseToMesh`; `UvProject`
runs `SetMeshUVsFromPlanarProjection`. It refuses to ship an empty mesh, reads
back real triangle and vertex counts, and tests watertightness with
`GetIsClosedMesh`. The composition report (`FMawuCompositionReport`,
`MawuRealmLockTypes.h:106`) folds these into `ProceduralTriangleCount`,
`ProceduralVertexCount`, and `bProceduralMeshesClosed`.

This is automation-covered three ways
(`MawuTests/Private/MawuRealmGeometryTests.cpp`):
`V7.Mawu.Realm.GeometryScript.ProducesWatertightVoxelAndCsgMeshes` asserts four
ops become four procedural meshes with real triangles and a watertight result
and **zero** static BasicShape fallbacks; `...RealisesSculptAndUvOps` proves the
sculpt and UV ops produce real geometry; and the builder-wiring test confirms
each builder op drives the expected realm `OperationKind`. The geometry is not a
placeholder — it is the literal proof that a builder edit becomes a mesh.

### Visual logic and TypeScript, one compile target

The scripting ladder lowers two on-ramps to one target.
`MoremiMawuStudioScriptCompileTarget::shared_v1()`
(`moremi-realm-server/src/lib.rs:1047`) names it precisely:
`wasm32-wasip2-component/studio-script-v1`, WIT world
`ixchel:studio/script@1.0.0`, **Scripted** sandbox tier, entry callback
`mawu_studio.on_event`. `compile_mawu_studio_visual_logic_to_wasm` (`:2498`)
validates a node-and-edge graph (no empty graph, no duplicate node, no dangling
edge) and lowers each node to a canonical `MoremiMawuStudioScriptOperation`;
`compile_mawu_studio_typescript_to_wasm` (`:2548`) lowers recognised API lines
to the same IR. Both produce a `MoremiMawuStudioCompiledScript` targeting the
same WIT world and tier — so a no-code trigger and an equivalent TS script land
on the same sandbox surface. The honest caveat (and why the task is `[ ]`): this
is a canonical-IR lowering plus a line parser, not a real TypeScript→WASM
compiler; the emitted `.wasm` name is derived, and the actual sandboxed WASM the
[Moremi server](../architecture/moremi-realm-server-and-netcode.md) runs is the
Wasmtime path documented on the Ixchel architecture page, not produced here.

### AI-assisted creation, gated and fail-loud

`@isis/three-d-pipelines`'s `mawu-studio-ai-creation.ts` is the generation gate
for the four AI tools (`MAWU_STUDIO_AI_CREATION_TOOLS`: `text-to-3d`,
`text-to-texture`, `text-to-world`, `text-to-npc`).
`evaluateMawuStudioGenerationPolicy` (`:274`) is a real Isis-policy + Sophia-
grounding check: it emits typed diagnostics for a missing creator or realm, an
unsupported tool, an empty or over-long prompt, a disallowed prompt term, an
unapproved model id, missing required Sophia grounding sources, and missing
attribution/licence on a cited source. Only when the policy accepts does
`runMawuStudioAiCreation` (`:717`) generate — and **absent an injected backend
it returns `backend-not-configured` rather than fabricating an artifact**, the
zero-stub fail-loud seam. When a backend _is_ supplied (the reference procedural
backend at `:664` for tests), every artifact carries a `buildAttribution` bundle
— `generatedBy: isis`, `groundedBy: sophia`, a prompt SHA-256, and per-source
licence/attribution — so provenance is authored in alongside the asset, not
bolted on. This is the same posture the V3 Lilith Studio takes on generative
costume, generalized to world content.

Upstream of generation sits the **Forge Assist** co-creator
(`@maya/forge-assist`), the AI that writes realm _scripts_. Its
`CapabilityPolicy` (`capability-policy.ts`) scans generated source for
`oshun.invoke("…")` and rejects, with named violations, any artifact that
invokes an undeclared capability, declares a capability outside the realm
allowlist, or touches a platform-owned namespace (identity, economy, safety) —
"there is no declaration that makes a realm script mint currency."
`ForgeAssistService` (`forge-assist.ts:141`) returns a `ForgeArtifactProposal`
(declared capabilities, a source SHA-256, model provenance) only after it clears
that policy, so a malicious _proposal_ never reaches the sandbox.

## The authoring workflow

The workflow is a pipeline: an edit becomes a layer, the layer is linted and
budget-checked and accessibility-checked, and a clean layer becomes a resource
manifest the realm composes. Two linters gate publish.

`lint_mawu_studio_layer_publish` (`moremi-realm-server/src/lib.rs:2600`) is the
referential gate. It rejects an empty layer id, a layer with no compiled
scripts, a script whose target/tier doesn't match the shared compile target
(`ScriptTargetMismatch`), and — the §14 "Done when" criterion — a script that
references an asset the layer never declared (`MissingAssetReference`). When the
diagnostics are empty it mints a `MoremiResourceManifest` (a `Content` resource
carrying the declared assets, the compiled WASM script entries, and the exported
event callback) — the same manifest shape the
[Ixchel runtime](../architecture/ixchel-modding-runtime-and-wasm-sandbox.md)
resolves and sandboxes.

`lint_mawu_studio_asset_budget` (`:2712`, the shipped `[x]` task) is the weight
gate. A realm declares a `MoremiMawuStudioRealmAssetBudget` (`:1329`) — a total
byte ceiling plus optional per-category sub-budgets — and the linter sums a
layer's sized assets, emits `TotalBudgetExceeded` and `CategoryBudgetExceeded`
diagnostics naming each offending asset largest-first with human-scale MiB
sizes, and passes a within-budget layer clean. Its eval
(`run_moremi_mawu_studio_asset_budget_eval`, `:2854`) and test
(`mawu_studio_asset_budget_eval_flags_overrun_and_passes_within_budget`,
`:13198`) pin a 17-vs-16-MiB total overrun (both assets named), an 8-vs-6-MiB
texture-cap overrun, and a clean 9-MiB layer.

Finally the **accessibility floor** is an eval, not a hope.
`runV7MawuAccessibilityEval` (`@v7/contracts`, `accessibility-eval.ts:182`) and
`lintV7MawuStudioAccessibilitySurface` (`:233`) check three required surfaces —
`mawu-studio-builder`, `abundantia-browser`, `default-realm` — against five
rules: voice/radio text-and-visual parity, colourblind-safe provenance diff,
keyboard/gamepad builder parity, a scalable-UI floor, and a reduced-motion
floor. The web Studio's `accessibility/` page renders this report live; the
linter is what guides an author to keep the floor intact. (Honestly: the eval is
real TypeScript over a fixture; the builder/browser _UI_ it scores is largely
the two-page seam above, which is why the accessibility task sits `[~]`.)

```mermaid
flowchart TD
  BRIEF["Creator brief"] --> ONRAMP{"on-ramp"}
  ONRAMP -->|in-realm builder| PLACE["EvaluatePlacement<br/>snap + bounds + op→realm map"]
  ONRAMP -->|visual logic / TS| COMPILE["compile_*_to_wasm<br/>shared canonical IR"]
  ONRAMP -->|AI tool| GATE["evaluateMawuStudioGenerationPolicy<br/>Isis policy + Sophia grounding"]
  GATE -->|accepted, no backend| FAILLOUD[["backend-not-configured<br/>(no fabricated artifact)"]]
  GATE -->|accepted + backend| ATTR["buildAttribution<br/>prompt hash + source licences"]
  PLACE --> LAYER["FMawuRealmLayer / Ixchel layer<br/>content hash"]
  COMPILE --> PUBLINT["lint_mawu_studio_layer_publish"]
  ATTR --> LAYER
  LAYER --> PUBLINT
  PUBLINT -->|MissingAssetReference / target mismatch| REJECT[["publish blocked, named errors"]]
  PUBLINT -->|clean| BUDGET["lint_mawu_studio_asset_budget"]
  BUDGET -->|over budget| WARN[["assets named largest-first"]]
  BUDGET -->|within budget| MANIFEST["MoremiResourceManifest"]
  MANIFEST --> IXCHEL{{"Ixchel: resolve + sandbox + compose"}}
  IXCHEL --> CLIENT["AMawuComposedRealmActor::ApplyLockFile<br/>renders pinned closure"]
```

## What gets created

Everything a creator makes lands as one of a small set of composable artifacts,
which is what lets a realm pin and reproduce exactly what it runs:

- **An Ixchel layer** (`FMawuRealmLayer`) — the unit the in-realm builder emits:
  an id, a priority, a content hash, and a list of realm primitives, each
  carrying the `OperationKind` that drives its Geometry Script realisation.
- **A resource manifest** (`MoremiResourceManifest`) — what a linted script
  layer becomes: declared assets, compiled WASM script entries, a sandbox tier,
  and exported callbacks, ready for capability-gated execution.
- **A compiled script** (`MoremiMawuStudioCompiledScript`) — the canonical-IR
  lowering of a visual-logic graph or a TS source against the one studio target.
- **An attributed AI artifact** (`MawuStudioAiCreationArtifact`) — a generated
  mesh/texture/world-layer/NPC profile with a media type, an Isis provenance
  bundle, and Sophia source attributions, or an honest `backend-not-configured`
  outcome.

These compose on the realm side: the
[Moremi server](../architecture/moremi-realm-server-and-netcode.md) resolves and
pins a lock file, and `AMawuComposedRealmActor::ApplyLockFile`
(`MawuComposedRealmActor.cpp:27`) renders the pinned, content-addressed closure
on every joining client — the same composition path the Ixchel architecture page
documents end to end.

## Edge cases and honest seams

- **A builder edit out of bounds is rejected, not clamped.** `EvaluatePlacement`
  refuses a primitive beyond `MaxDistanceFromOriginCm` with a named reason; a
  missing id or non-positive grid fails the same way.
- **A coverage requirement fails the whole publish.** If a draft sets
  `bRequireDesktopVrParity` and one edit lacks VR parity, `PublishIxchelLayer`
  returns unpublished with the parity reason — all-or-nothing, like V3's premium
  dual-authoring parity.
- **A script referencing a missing asset cannot publish.** The publish linter
  emits `MissingAssetReference` naming the script and the asset; no manifest is
  minted.
- **AI generation fails loud without a model.** No injected backend yields
  `backend-not-configured`, never a fabricated mesh — the zero-stub rule made
  mechanical.
- **The scripting compile is a model, not a toolchain.** Visual logic and TS
  lower to a shared canonical IR; the real sandboxed WASM is the Wasmtime
  runtime on the Ixchel page, not a binary produced here.
- **No DCC import exists.** FBX/glTF/USD/Alembic import, photogrammetry/splat
  ingest, and Nanite/LOD auto-optimization are spec, not code; the in-realm
  builder is the committed geometry path.
- **The web Studio is two route shells.** `accessibility/` and `localization/`
  render real evals; the full builder/browser web UI is product surface.

## Where this connects

- [Ixchel: the sandbox and modding runtime](./ixchel-sandbox-and-modding.md) —
  how the manifests and layers Mawu Studio emits are resolved, capability-gated,
  budgeted, and composed; the runtime that makes "run untrusted creator code"
  safe.
- [Abundantia: the creator republic](./abundantia-creator-republic.md) — how a
  finished realm, mod, or Collection is distributed cross-platform and paid for
  (engagement pool, direct sale, dependency-revenue chains).
- [../architecture/ixchel-modding-runtime-and-wasm-sandbox.md](../architecture/ixchel-modding-runtime-and-wasm-sandbox.md)
  — the deep companion: the Wasmtime sandbox tiers, the PubGrub resolver, the
  content-addressed store, `forge-compositor`'s provenance-stamped composition,
  and the lock file the client renders.
- The feature hub: [../V7_features.md](../V7_features.md).
