feat(proxy): tide quality — prominence filter, midnight stitch, level numbers Addresses the accuracy issues found comparing 장환/고마리 against the reference app: - tideExtrema: cleanExtrema() prunes hourly-sampling wiggles by prominence (< max(0.15m, 0.12*range)) and collapses same-type runs — removes the spurious midday high/low (e.g. 6/5 14:00). Noise guard still uses raw extrema count so East-coast small-tide still degrades. - khoaModel: fetchModelTideDay now stitches the previous/next day's zeta (±1 day) so near-midnight highs/lows are detected (6/5 00:40 high now caught at 00:22). Noise judged on the target day only so the stitch doesn't inflate the count. - levels.ts annotateLevels(): per-event delta (▲/▼ vs previous extremum) and daily range — datum-independent, so reliable even for the MSL-relative model. Applied to both official and model tides; TideEvent.delta + TideDay.rangeCm added. Verified: 장환 6/5 -> clean 4 events (만조 00:22, 간조 06:55 ▼247, 만조 12:15 ▲162, 간조 18:41 ▼233), range 318cm; 6/6 clean. vitest 28/28. Constraint: model levels stay MSL-relative; only deltas/range are shown as absolute cm because differences are datum-independent. Confidence: high Scope-risk: module Reversibility: moderate Directive: Remaining ~15min early bias on bay points is a separate task (nearest-station time-offset correction); not addressed here. Tested: vitest 28/28; live HTTP 장환 6/5·6/6 (spurious extremum gone, midnight high recovered, deltas/range present). Not-tested: prominence threshold on diurnal-inequality coasts (could over-prune a real secondary); revisit if reported. Related: docs/BACKLOG.md 3-A/5 🐙 Autopus