# Build and package

## Editor workflow

Open **Build > Build Package** or the **Build** panel. Select `development`, `qa`, or `release`, then
choose **Build** or **Build and Run**. Compilation and packaging run in the background and stream into
the panel. **Cancel** terminates the active packager/compiler process tree. **Reveal Output** opens
the last successful package directory. The editor refuses to start a package while any scene tab is
modified; save all tabs first. Closing the editor cancels and joins the build worker.

Every build validates before and after compilation. Blocking findings must be repaired through the
owning scene actor or asset. The final asset snapshot must remain unchanged while staging is
assembled; otherwise the build asks for a retry and leaves the previous package untouched.

## Headless workflow

```bash
cargo package-project --profile development
cargo package-project --profile qa
cargo package-project --profile release

# Validate/package another checkout
cargo package-project --project /path/to/project --profile release
```

`--skip-build --artifact /path/to/game` is reserved for package-pipeline tests or repackaging an
already-built matching Cargo artifact. Normal editor and CI workflows must not use it. Cargo JSON is
the authoritative executable location for ordinary builds, including custom target directories.

## Profiles and output

Profiles live in `assets/build_profiles/*.ron`. The editor's sandbox scaffold creates all three
standard profiles even though the engine Cargo workspace remains separate from that project root.
Output must use a dedicated `dist/<name>/` directory under a real, non-symlinked project `dist/`.
A non-empty destination is replaceable only when its `build-metadata.json` proves that the packager
owns it; profile typos therefore cannot prune source or unrelated user files. Runtime asset symlinks
and unreadable traversal entries are also rejected. The standard outputs are `dist/development`,
`dist/qa`, and `dist/release`; `dist/` is ignored by Git.

`development` uses the optimized non-LTO package profile and forces Forward GI in the packaged
settings for portable iteration. `qa` retains line tables and preserves the authored rendering
policy. `release` preserves authored rendering, uses thin LTO, and strips symbols. `dev` and
`hot-reload` Cargo features are editor iteration modes and are intentionally rejected by packaging.
Windows MSVC QA output also includes `blacksite.pdb`; Linux QA line tables remain embedded in the
binary. Profile-selected defaults must be regular `.scn.ron` scenes under `assets/levels/`, where the
shared validator audits their complete component dependency graph as well as schema/composition. The current native
layout supports desktop Linux and Windows targets; web, Android, iOS, and macOS application bundles
need dedicated platform packaging and are rejected instead of producing an incomplete output.

Each output contains:

- `blacksite` (`blacksite.exe` on Windows);
- `blacksite.pdb` for Windows MSVC QA profiles;
- runtime `assets/` with editor/recovery/source-only content excluded;
- `build-metadata.json` with the toolchain, commit/dirty state, profile inputs, and BLAKE3 content
  hashes.

Files are assembled in an authenticated sibling staging directory copied from prior output, then
rehashed and promoted only after metadata and the content manifest are complete. Staging never shares
writable file inodes with the published package; Windows removal also clears read-only attributes only
inside authenticated owned work trees. A per-output OS lock blocks concurrent publishers. The next
run removes an owned interrupted staging tree and restores a verified prior backup; unknown lookalike
files/directories are left untouched and reported. A cancellation, validation error, or I/O failure
never publishes a partial package.

Run a package from its output directory so Bevy resolves the packaged `assets/` root:

```bash
cd dist/release
./blacksite
```

The standalone binary loads `default_level` from its packaged `assets/project.ron` through the same
schema-aware dynamic-scene loader used by runtime prefab assets. The editor leaves that authored
startup to `SceneIo`; its generated arena remains only as the failure fallback when the startup scene
cannot be loaded. Build and Run reports a clear host mismatch instead of trying to execute a
cross-compiled package for a different operating system or CPU architecture.
