# Formatting and component boundaries Run `npm run format` to format the files in `scripts/format-scope.json` plus automatically discovered runtime JavaScript in `scripts/format-runtime.json`, and `npm run format:check` to check that same list without writing. CI checks the combined scope on Linux and Windows. Prettier is pinned in the development dependencies; use the installed version so local and CI output agree. The shared configuration specifies two spaces, single quotes, semicolons and LF endings. Owned runtime modules are discovered automatically; add their tests and other non-runtime files to the explicit list as they are adopted. Keep mechanical formatting in its own commit after behavior is stable. Existing source-text regression assertions still apply; investigate failures and preserve their behavioral coverage when a move or line wrap changes a tested shape. Files outside the runtime roots and explicit list retain their surrounding style until deliberately adopted. Generated output, local configuration, browser evidence and bundled datasets are excluded. The formatter validates every entry before writing any file. New world text labels must use the world-overlay host; Cesium text labels are forbidden. ## QA scripts New `scripts/qa-*.mjs` scenarios use `scripts/qa/browser.mjs` for headless launch and bounded shutdown, and `scripts/qa/ready.mjs` for application, camera and frame readiness. Select the GPU backend with `QA_ANGLE`. Keep timed pauses only when elapsed time is part of the assertion, and explain that measurement. Read scene state through the globe contract or the QA probe; native reads belong only in explicit engine-adapter checks. The counters in `node scripts/report-qa-harness.mjs` must not grow; lower the baseline with `--write-baseline` after removing duplication. ## Current component ownership Package imports use `gods-eye-view`; `package.json` is the authoritative export inventory. Use declared exports rather than reaching into internal files. | Owner | Responsibility and lifetime | | ---------------------- | ------------------------------------------------------------------------------------------------------- | | `src/app/` | Construct supplied components, share scene/request services, cancel startup and dispose the application | | `src/standalone/` | Select the default catalog, local sources and setup controls | | `src/ui/` | Navigation generations, restoration, visual state, panel snapshots and their subscriptions | | `src/data/` | Lifecycle, context and feed state; legacy default-layer facades | | `src/layers//` | Source acquisition, records and shared contract displays with explicit lifecycle owners | | `src/sources/` | Portable protocols and source contracts; request state belongs to each factory instance | | `src/geo/` | Engine-neutral WGS84 maths, ported from Cesium, never imports Cesium | | `src/globe/` | Engine-neutral globe contract and its test support; engines only in `globe/cesium`, `globe/navara` | | `src/services/` | Supplied application operations; scene construction owns caches and cancellation | | `src/voice/` | Portable action schemas/session, common controls, action execution and separate protocol adapters | | `server/providers/` | Node route factories, process-scoped provider caches and shutdown cleanup | | `server/standalone/` | Environment, local settings writes and server composition | See [application construction](APPLICATION.md) and the [infrastructure contract](INFRASTRUCTURE-LAYERS.md) for construction interfaces. ## Import direction gates `npm run check:boundaries` runs two complementary checks: 1. `scripts/check-import-directions.mjs` parses every runtime JS/MJS/CJS file in `src/` and `server/`, including files unused by the current bundle. Static, literal dynamic and re-export edges are checked; computed module imports and CommonJS `require` are rejected. Browser graphs cannot reach Node, server or test modules through helpers. Reusable modules cannot select standalone setup, and provider modules cannot import application/rendering modules. 2. `scripts/check-package-boundaries.mjs` builds every declared export without app Vite configuration or environment files. `scripts/package-boundaries.json` assigns each export exactly once and lists its owned modules and external dependencies. Shared foundations use directory entries: `src/i18n/`, `src/geo/` and `src/globe/`. An entry ending in `/` owns the files below it; `src/globe/` excludes `cesium/`, `navara/` and `testing/`, which need separate ownership. The import-direction gate still enforces engine rules. Aggregate groups use directories where their module lists cover the directory; small groups retain explicit snapshots outside the shared foundations. Unused imports still count. Node exports have only a `node` condition; browser groups cannot use build-only dependency exceptions. Run `node scripts/check-package-boundaries.mjs --write` to regenerate each group's `modules` list in `scripts/package-boundaries.json`, retaining useful entries in order and appending newly reached paths in sorted order. Directory entries stay directories while they own reached modules; they never expand into file lists. Without `--write`, the check rejects both undeclared reached modules and declarations no longer reached, printing additions and removals for each changed group. A directory becomes stale only when no reached module belongs to it. Review the manifest diff like a lockfile diff before accepting changes to ownership. Portable source graphs cannot reach application/rendering, Node, Cesium or browser globals. This includes `sources/*`, dedicated `layers/*/source` exports, flight/military/vessel record and ingestion exports, action schemas, the session interface, lifecycle and feed state, and every runtime file in `src/geo/` (the engine-neutral geometry ported from Cesium). The browser-global rule reserves platform names such as `document` and `window` in these modules; it is an architectural check, not a JavaScript sandbox. The globe contract (`src/globe/*.js` and `src/globe/testing/**`) cannot reach `cesium`, `@cesium/*`, `three`, `postprocessing` or `@navaramap/*`, directly or through helpers, nor import an engine implementation; the `src/globe/cesium/**` graph reaches no Navara/three package or `src/globe/navara/**` module, and the `src/globe/navara/**` graph no Cesium package or `src/globe/cesium/**` module, through helpers too. Outside its own directory, `src/globe/navara/**` is reached only through a literal `import()` (the app's `?engine=navara` mode), so Navara stays out of the Cesium-mode bundle. Common voice controls cannot depend on a Realtime protocol implementation. Negative fixtures cover indirect helpers, self-package imports, symlinks and unreachable files. Runtime SDK imports are restricted by directory, including unreachable modules: `cesium` and `@cesium/*` belong in `src/globe/cesium/`; `three`, `postprocessing` and `@navaramap/*` belong in `src/globe/navara/`. Package subpaths, re-exports and literal dynamic imports obey the same rule, and the `