# ADR 0025: Project Root Is a Startup Boundary

## Status

Accepted

## Context

Bevy configures `AssetPlugin.file_path` before editor plugins and project settings initialize. The
asset catalog, scene loader, import pipeline, session state, and runtime game systems must all agree
on one project root. Changing only editor metadata in a running process leaves `AssetServer` and
already-created handles attached to the old project, which can silently read or write the wrong
content.

Projects also need stable identity and enough template metadata for a launcher to distinguish a
game workspace from a disposable sandbox without inspecting arbitrary project contents.

## Decision

- Select and validate the project root before constructing the Bevy `App`. `--project <root>`, the
  graphical launcher, and recent-project resume all feed the same pre-engine activation function.
- Do not implement in-process project switching. **Switch Project** exits or relaunches through the
  launcher so the next process creates `AssetPlugin`, settings, catalog, and session state from one
  root.
- Extend `assets/project.ron` with backward-compatible `project_id`, `project_kind`,
  `template_version`, and capability tags. Legacy manifests receive safe defaults; new projects
  receive a UUID.
- A valid project has a parseable manifest, a project-relative default level that cannot escape the
  root, and a default level that passes the shared scene validator.
- The standalone `GamePlugin` materializes that `default_level` through the schema-aware Bevy
  `DynamicWorld` loader. Embedded editor startup explicitly defers this step so `SceneIo` remains
  the sole owner of the active authored document, tabs, composition, and recovery state.
- Sandbox scaffolding writes only to a missing or empty destination. It creates the standard asset
  directories, a schema-current empty level, and a manifest using transactional writes.
- Recent-project presentation filters missing, invalid, and duplicate roots before showing them.
- On Linux, launcher-to-editor and editor-to-launcher handoffs use independent transient user
  services with an explicit working directory and a bounded display/session environment allowlist.
  Closing either source process therefore cannot tear down the process it launched.

## Consequences

- Project activation cannot leave the editor half-connected to two asset roots.
- Packaged and workspace game binaries start in the validated authored default level instead of the
  procedural editor fallback arena; the editor cannot race a second runtime-owned scene load.
- Switching projects requires a process boundary, but startup remains deterministic and testable.
- Project scaffolding is intentionally conservative and cannot merge into a directory containing
  user data.
- Template migrations and capability negotiation can evolve independently of the project-settings
  file format version.
- The service-manager handoff is Linux-specific; other platforms use the local process-spawn
  fallback until native packaging provides a stronger lifecycle boundary.
