# Terrain World v2 consumer contract

V2 adds explicit elevation policy and patch water coverage to the
[v1 geometry and scenery contract](FORMAT.md). Metres, grid ordering, triangle
diagonal, source namespaces, hashes and exact boundary heights/normals retain
their v1 meanings. Compiler release versions are separate from schema versions.

| Schema | Purpose |
| --- | --- |
| `layout-v2.schema.json` | Input layout with optional sea policy |
| `world-v2.schema.json` | Descriptor and terrain/scenery/boundary/report definitions |
| `source-v1.schema.json` | Original viewer-bundle v2 input contracts, unchanged |

All package documents use `schema_version: 2`. A root v2 with any v1 companion
is invalid even if its hash matches. V1 layouts continue producing v1 packages;
v2 layouts always produce v2 packages. Standalone validation needs no original
ZIPs or models.

## Policy and transformation

V2 layouts optionally include `sea_level_policy`; omission resolves to
`{"mode":"preserve"}`. The descriptor and report always contain the resolved
policy. Preserve accepts no target. Normalization requires exactly:

```json
{"mode":"normalize","target_sea_level_m":0}
```

Targets may be negative or nonzero, but must be finite. For each source:

```text
vertical_offset_m = target_sea_level_m - terrain_metadata.sea_level_m
compiled_height = decoded_original_height + vertical_offset_m
```

Preserve mode uses zero offset. The compiler translates a Float64 working
array once before generating Hermite strips/corners and before sampling
placement heights. The consumer must use the compiled heights directly.
Neither renderer nor scenery importer should add the offset again.

Every source adds `vertical_offset_m` and `compiled_elevation`, containing
`minimum_elevation_m`, `maximum_elevation_m`, `sea_level_m` and
`lowland_reference_elevation_m`. Each equals the corresponding original value
plus the offset. Minimum must remain less than maximum, the span must be finite,
and sea/lowland references must remain within it. Normalize's effective sea
must exactly equal the target. Numerically unrepresentable transforms are
rejected before connector allocation/publication.

`terrain_metadata` remains original export metadata, including the original
uint16 references. Effective elevations do not define a new encoding. Original
ZIP, manifest, entry and unverified Float32 hashes remain unchanged provenance.
Validate source samples against effective bounds, including normal decode
roundoff tolerance, rather than original encoding bounds. Placement heights
must match compiled triangle queries; X/Z, IDs, visibility, rotation, scale,
asset references and entity relationships retain their v1 meanings.

## Water coverage

Each water region is `{source_id, patch_id, bounds_m, level_m}`. Its bounds
must exactly match its patch and its source ID must match the patch's source
ID. Generated strips/corners have `source_id: null`.

Preserve has exactly one region per source patch at that source's original
sea level. Connectors remain dry. Normalize has exactly one region per patch,
including every strip and corner, all at the common target. Duplicate,
missing or extra regions are invalid.

These records define coverage planes, not shoreline meshes. Above-level terrain
occludes water; below-level terrain is submerged, including isolated
below-level depressions. Ocean-connected hydrology is outside this contract.
An engine may combine normalized regions into one plane bounded to the world
rectangle to avoid transparent seams. Queries, terrain colours and vegetation
must use the common sea level everywhere in a normalized world.

## Report and publication

The report adds the resolved `sea_level_policy` and `source_elevations`, in the
same order as descriptor sources. Each record contains `source_id`,
`original_sea_level_m`, `compiled_sea_level_m` and `vertical_offset_m`, equal to
the source metadata/effective fields. Patch statistics use final terrain;
Hermite overshoot and steep-slope warnings remain unchanged in meaning.

Companion SHA-256 hashes include these versioned documents. Deterministic
ordering, staged validation, atomic publication and refusal to replace existing
output paths are retained. Opt in by compiling a v2 layout into a new directory;
do not edit a generated v1 package or merely change its version number.
