Field Engineering Report · 2026-06-10 · Issue 007

Reading the Sun — vegetation that knows which way a slope faces

The valley's land classification grew the same vegetation on a north slope and a south slope — no notion of aspect, the single most visible fact of a real mountainside. In reality a shaded, pole-facing slope holds moisture and grows forest; the sun-facing slope across the draw bakes to dry scrub. This pass made the sim read the sun — and, because vegetation is cover and concealment, it had to be done the hard way: measured against combat balance, across three strengths, until it earned its place on by default.

64% was 59%forest on shaded slopes
56% was 48%scrub on sunny slopes
1.08 was 1.17US KIA — down on both seed sets
byte-identicalvillage/COP siting · gate-overwatch
Bar chart: forest-on-shaded-slope rose from 59% to 64%, scrub-on-sunny-slope from 48% to 56%
The shipped signal (aspect-probe.ts): vegetation now leans the ecologically-correct way — forest toward the shaded draw, scrub toward the sunny spur. Modest by design (0.05 is the strength that clears the no-stall guard), but real and on by default.

01The bug: vegetation that ignored the sun

classifyLand chose forest vs scrub from a moisture noise + a crude north-y gradient — no aspect term. A new oracle (scripts/aspect-probe.ts) measured the tell: of forest cells on real slopes, only 59% faced the shaded (north) side; of scrub, 48% faced the sun — barely better than a coin flip. The mountainside didn't read the sun.

moist += aspectShade · STRENGTH aspectShade = (∂elev/∂y) / slope on faces steeper than 0.62 // which way the slope FACES north/pole-facing (shaded) ⇒ wetter ⇒ forest ; sun-facing ⇒ drier ⇒ scrub

Gated to the steep faces (slope > 0.62), above the terraced-cropping band — which is why village & COP siting and the hard-won gate-overwatch geometry stay byte-identical (route-quality 48 / ratio 1.12 unchanged, copaudit gate-overwatch 0/9).

02Why this was the hard kind of change — and how it was earned

Vegetation isn't cosmetic here: forest conceals (0.6) more than scrub (0.5), and that field decides who gets seen and shot. So moving forest onto the shaded ambush faces changes the firefight. The honest way to ship it was to measure that — at three strengths:

strengthsignalbalance (same-seed 12×50 A/B)
0.16strongKIA 1.17→1.83 (+56%) · stranded — too hot
0.025weakKIA 1.17→1.50 · stranded — chaotic, also bad
0.05 (shipped)realKIA 1.17→1.08 (down) · 0 stranded · WIA/enemy shift by terrain

The balance moves chaotically with strength (the KIA isn't even monotonic, and strandings flicker in and out) — because changing which terrain a firefight happens on reshuffles every ambush. 0.05 is the strength that lands well: it clears the no-stall guard where 0.16 and 0.025 don't, and the permanent loss (KIA) goes down.

Held out (Law 3 — the honest test). On a fresh hold-* seed set, aspect ON gives KIA 1.17→1.08 (down, same as the tuned set) and WIA 8.50→8.08 (down) — and the lone stranding present is pre-existing (the aspect-OFF baseline strands the same element, so aspect adds none). The catch it surfaced, stated plainly: the WIA/enemy texture is genuinely terrain-dependent — bloodier on the tuned seeds (WIA +39%, enemy +29%), quicker on the held-out (WIA −5%, enemy −25%). So the only seed-robust claims are the ones that ship it: vegetation reads the sun, KIA never regresses, no new strandings, siting byte-identical. The combat intensity simply varies with the ground — which is itself realistic.

03What it costs, honestly

Mechanism: lib/sim/terrain.ts (classifyLand aspect term, ASPECT_STRENGTH). Oracle: scripts/aspect-probe.ts · A/B: ITM_ASPECT. Raw record + 3-strength sweep: docs/progress/2026-06-10-open-issues/007-aspect-ecology/. Built by an autonomous agent fleet; shipped on by default only after the balance earned it.