# Persistent build preferences

Saved building preferences use `ROMCP_PROJECT_ROOT` when configured, fall back to legacy `DOMINUS_PROJECT_ROOT`, or discover the nearest `.dominus/project.json` from the MCP working directory without crossing a Git boundary. An explicitly empty environment override is rejected. The control panel and building tools use the same discovery behavior. Each published place gets its own `.dominus/build-style-<placeId>.json` in that project root. A restart or a new MCP conversation reloads that file. Preferences do not apply across different place IDs, including places in the same universe.

For visual editing, open the existing control panel with `show_dominus_ui`, scroll to **Build preferences**, select a connected published Studio place, and load its preferences. Edit the fields and save, or clear saved defaults. The panel uses the same store as MCP building tools. It requires a fresh load after a target change or stale revision; routine status refreshes do not overwrite an edited form. If the project root is not configured, the panel explains the required setup and disables saving.

Use `studio_build_style` with `{ "action": "get" }`. To replace the profile, pass the returned revision:

```json
{
  "action": "set",
  "expectedRevision": "missing",
  "style": {
    "material": "Plastic",
    "color": "#F3C54B",
    "anchored": true,
    "canCollide": true,
    "surfaces": {
      "TopSurface": "Studs",
      "BottomSurface": "Inlet"
    }
  }
}
```

`missing` is valid only when no profile exists; otherwise use the actual revision from get. Set replaces the entire profile, so merge retained preferences into the new style before saving. An empty style resets all saved defaults. Stale writes fail and preserve the current profile. A file lock prevents concurrent writers from silently overwriting each other; an orphaned lock after a process crash requires inspection before removal.

Direct part creation and procedural program templates inherit these values. Supported BasePart classes created through `studio_apply` also inherit saved defaults. The shared class list covers Part, WedgePart, CornerWedgePart, TrussPart, MeshPart, SpawnLocation, Seat, and VehicleSeat. Precedence follows existing Studio application behavior: explicit `properties` win over explicit part fields, which win over saved defaults. The typed part tools retain their anchored default when no anchoring choice is supplied; generic atomic creation preserves engine defaults for settings absent from the profile. Clones retain their source appearance. Existing-instance edits, non-part classes, generated mesh workflows, arbitrary Luau, and UI tools do not automatically acquire this profile.

All six faces can specify `Smooth`, `SmoothNoOutlines`, `Studs`, or `Inlet`. Material names are checked by Studio when applied; saving a string is not proof that the engine supports that material. Hex colors must contain six digits. Invalid files and unsupported surface names fail explicitly instead of silently discarding preferences.

`studio_review_3d` reports all six face-surface values alongside material for each sampled BasePart. Its `buildStyleReview` compares the returned sample with saved material, color, anchoring, collision, and surface preferences using that same Studio response. It adds no Studio request. The report includes a profile revision, difference and unknown-value counts, and up to 20 detailed differences with instance references. `omittedDifferences` counts additional differences in the sample; `sceneTruncated` warns when the scene report excluded parts. Missing properties from older plugins count as unknown. Missing preferences or unavailable scene data do not produce a passing verdict; unreadable preferences leave the geometry review available with an explicit unavailable status.

Differences are advisory because explicit overrides can be intentional; reviewing never changes parts. A successful save proves persistence, not appearance in Studio. Inspect the built result and keep normal visual verification for meshes, CSG, and shapes where engine face surfaces do not guarantee visible studs. No live Studio visual test was performed in this implementation pass.

This version provides place-wide defaults, a visual editor, and a shared storage/resolution service. Browser checks verified save, reload, reset, and layout at desktop and 360px widths against the real local settings endpoint with simulated Studio connections. MCP integration tests verify inheritance and explicit overrides for direct parts, procedural programs, and atomic creation, while preserving clones and UI instances. Review tests cover surface/material differences, unknown data, case-insensitive hex colors, explicit false values, and bounded reporting. Named profiles and subtree overrides remain part of the broader v3 work. More public API/SDK operations are deferred.
