* fix(posture): compute vessel counts server-side from AIS stream
trackedVessels was hardcoded to 0 in seedTheaterPosture(). The relay
has live AIS data in the vessels Map but never used it for posture.
Now counts military vessels (shipType 35/50-59, naval prefixes, MMSI
patterns) within each theater's bounds using the same identification
logic as isLikelyMilitaryCandidate(). Vessels seen in the last 6h
contribute to both the vessel count and the combined posture level.
This ensures the bootstrap theater posture data shows accurate vessel
presence regardless of whether the client has AIS toggled on.
* perf(posture): use candidateReports instead of iterating all vessels
candidateReports is already pre-filtered for military candidates on
AIS message arrival. No need to re-apply isLikelyMilitaryCandidate
on every vessel for every theater. Reduces ~90k function calls to a
simple bounds check on the candidate set.
* fix(posture): address vessel count issues in theater posture
1. Remove early exit on flights.length === 0 so vessel-only scenarios
still seed posture (P1 — Codex review comment)
2. Add isStrictMilitaryVessel() to filter candidateReports to shipType
35/55 and named naval vessels only — drops tugs, pilot boats, SAR
craft (shipType 50-59) that inflate counts in maritime theaters
3. Cap vessel contribution at floor(elevated_threshold / 2) to prevent
naval traffic from dominating flight-calibrated posture thresholds
4. Update seed-meta recordCount and log to include vessel counts