# M02-GMP-TERRAIN-QUERY-001 — Player terrain query boundary

<!-- OPENWC_CLAIM:M02-GMP-TERRAIN-QUERY-001:sindo-main-codex:2026-07-16 -->
<!-- OPENWC_HANDOFF:READY:M02-GMP-TERRAIN-QUERY-001:a45d521 -->
<!-- OPENWC_INTEGRATION:ACCEPTED:M02-GMP-TERRAIN-QUERY-001:f5bb64e -->

## Ownership

- Target: M02
- Program: GMP/RND
- Owner/Agent ID: sindo-main-codex
- Branch: `work/sindo-main-codex/m02-terrain-query`
- Lease expires UTC: 2026-07-16
- Integrator: M02 milestone integrator

## Outcome

Introduce a typed `TerrainQuery` boundary and move ADT loading, caching, chunk
selection and height interpolation out of `ThirdPersonWowController` without
changing current spawn/ground-snap behavior.

## Non-goals

- Change ADT topology, coordinate formulas, terrain mesh or renderer caches.
- Add physics collision, slopes, water, jump/fall/swim or server movement.
- Reuse the streaming renderer cache before its public terrain-query contract exists.
- Extract camera or character presentation.
- Mark M02 complete or edit its checklist/Evidence.

## Paths

- Exclusive: `src/gameplay/terrain/`, `src/tools/verify_terrain_query.gd`,
  `docs/modules/terrain-query.md`, this claim
- Shared/hotspots: `src/scenes/player/third_person_wow_controller.gd`,
  `src/tools/verify_player_input.gd`,
  `src/tools/verify_coordinate_conversion_boundaries.gd`,
  `docs/modules/local-player-movement.md`,
  `docs/modules/README.md`
- Generated/ignored: local `.godot`, native DLL, generated ADT resources and renderer corpus

## Contracts and data

- Public API: `TerrainQuery.sample_ground_height(GodotWorldPosition)` returning
  immutable `TerrainGroundSample`
- Production adapter: `AdtTerrainQuery` with owned per-tile parse cache
- Test/data-source seam: optional ADT tile loader callable at construction
- Coordinate contract version, ADT format, renderer cache and persistence: unchanged
- Consumers: current player scene; future movement/collision policies

## Dependencies

- Requires: merged movement controller on master `5206c42`
- Blocks: camera/presentation extraction from the player hotspot
- External state: production uses existing native `ADTLoader`; synthetic tests need no proprietary data

## Verification

- Commands: synthetic height/cache/failure verifier, player input/movement
  regressions, asset-free scene, coordinate/StreamingFocus gates, renderer dry-run
  and repository gates
- Fixtures: synthetic 145-height chunk payload and injected flat terrain query
- Fidelity evidence: preserves existing outer-grid bilinear interpolation,
  spawn ground offset and per-tick snap formula only
- Performance budget: one cached tile lookup and local interpolation per ground query;
  no new I/O after first tile load

## Documentation deliverables

- Inline public API docs for query, sample and ADT adapter
- Terrain-query module spec with inputs/outputs, data-flow, cache lifecycle and sequence diagrams
- Updated movement/coordinate consumer boundaries, source maps and module registry

## Simplicity and naming

- Important names: `TerrainQuery`, `TerrainGroundSample`, `AdtTerrainQuery`
- Simplest approach: one narrow query contract, one typed result and one existing-format adapter
- Rejected complexity: general collision framework, terrain service locator and renderer-cache coupling
- Unavoidable complexity: ADT 145-height layout and chunk lookup stay isolated in adapter
- Measured optimization evidence: existing per-tile cache retained; no new optimization

## Status

- State: ready-for-review
- Done: typed query/sample contract, cached ADT adapter, player migration,
  synthetic interpolation/cache/failure tests, injected scene regression and documentation
- Next: M02 integrator reviews and merges before camera-rig extraction
- Blocked by:

## Handoff

- Commit: `a45d521`
- Branch: `work/sindo-main-codex/m02-terrain-query`
- Outcome: `ThirdPersonWowController` no longer loads ADTs, caches tile
  dictionaries, selects chunks or interpolates height grids. It consumes a
  replaceable typed `TerrainQuery` and retains only existing offset/snap policy.
- Public contracts: additive immutable `TerrainGroundSample`, replaceable
  `TerrainQuery`, cached `AdtTerrainQuery` and player `set_terrain_query`.
  Coordinate contract version, ADT/native format and renderer caches are unchanged.
- Verification: `TERRAIN_QUERY PASS contract=4 interpolation=1 cache=1
  failures=2 player_injection=1`; player-input and local-movement regressions
  passed; asset-free scene exited `0`; coordinate boundary passed with five
  required consumers and StreamingFocus passed; renderer dry-run passed eight
  pre-capture gates and seven checkpoint plans; coordination/documentation/diff gates passed.
- Fidelity: synthetic fractional-grid fixture locks the inherited 145-height
  outer-grid bilinear result within `0.002` Godot units; injected scene locks
  spawn offset `0.05` and physics snap. This is sandbox-regression evidence,
  not build-12340 triangle/hole/collision parity.
- Local verification inputs: isolated worktree reused the existing ignored
  native DLL and generated ADT resource scripts. Proprietary extracted data and
  character GLB were absent, so renderer dry-run logged expected missing-corpus
  diagnostics while all contract steps returned success.
- Rebuild/migration: none; caches are transient and existing formats remain unchanged.
- Remaining risks: first ADT parse remains synchronous as before; unavailable
  tiles cache until query replacement; player still owns snap policy; exact
  ADT triangle choice, holes, slopes, liquids and collision remain open.
- Documentation: inline public APIs plus `docs/modules/terrain-query.md` with
  inputs/outputs, data-flow, cache state and cross-boundary sequence diagrams,
  ownership, failure/recovery, capability status and source map. Coordinate and
  movement consumer specifications were updated.
