# Cascades — 5 GHz DFS channel plan (data-driven, scan-first) APPLIED + validated

## User
- **User:** Howard Enos (howard)  (Howard directed: gather ALL data first, then choose from facts)
- **Machine:** Howard-Home
- **Role:** tech

## Summary
After the earlier blind non-DFS attempt failed + Howard's correction (scan FIRST, decide from data), I
completed the full 5 GHz channel survey (74/74), let the DATA pick the channels, and applied a clean-DFS
plan. Result: **5 GHz retry roughly halved (8.7 -> 3.8 avg, median 8.2 -> 2.1), satisfaction healthy
(median 99), voice back on 5 GHz.** This is the validated win the neighbor-only approach couldn't produce.

## The data that drove it (survey-collect, 74/74 APs, iw survey busy%)
Fleet-wide measured 5 GHz channel congestion (median busy%):
- **DFS (52-64, 100-144): ~2-3% busy** (nearly empty — the clean spectrum here).
- Non-DFS UNII-1 (36-48): ~10% (ch44=22%, ch36=12%).
- Non-DFS UNII-3 (149-165): ~10-14% with the WORST channels on property -> **ch157=28%, ch149=12% (max 75%)**.
FACT: at this site the non-DFS channels carry 4-5x the congestion of DFS (consumer/neighbor gear avoids
DFS). The plan's "non-DFS only" rule was measurably WRONG here -> Howard's call: use the clean DFS channels.

## What was applied (data-driven)
- **Channel palette = the 8 clean 40 MHz DFS blocks**: 52, 60, 100, 108, 116, 124, 132, 140 (all measured
  <=3% busy).
- **Per-AP assignment**: each non-mesh AP got its locally-cleanest DFS channel (from its own survey row),
  graph-colored against the AP-to-AP neighbor SNR matrix + load-balanced. Local-search optimization ->
  **0 strong co-channel pairs, 0 all-neighbor pairs, avg chosen-channel busy 3.5%**.
- **Width 80 -> 40** (more spatial reuse; voice is low-bitrate). Applied channel+width in one PUT per AP.
- **72 non-mesh APs**; mesh excluded (2nd Floor Atrium + children CC Bridge/salon/108 stay on auto -> adapt).
- **Voice phones nudged** (kick-sta) after the channel-change scatter -> 17 Poly back on 5 GHz; 3 remain on
  2.4 = the genuine weak-coverage rooms (515/MemCare) that next week's new APs fix.

## Validation (vs start-of-night baseline)
- 5 GHz retry: **8.7 -> 3.8 avg (-56%), median 8.2 -> 2.1 (-74%)**.
- 2.4 retry: 12.0 -> 13.2 (~baseline; the 2b power work holds).
- Satisfaction: 98.7 -> 97.6 avg / **median 99** (healthy; avg still converging up post-change).
- Voice: 31/31 (29 mid-reassoc at one read), 17 Poly on 5 GHz + 3 coverage-cases on 2.4 + 9 wired.
- **All 72 APs HOLDING their DFS channel (0 radar vacates), evenly spread across the 8 channels.** Stable.

## NET state kept tonight (the validated wins)
1. **2b** — 2.4 power Low/full -> MEDIUM on 47 radios (over-thinning fix + MemCare sane power).
2. **5 GHz DFS plan** — 72 non-mesh APs on clean DFS 40 MHz, 0 co-channel, retry halved.
3. CSCNet BSS-transition on.
- BLOCKED: 6 GHz (WPA3 mandate on the WPA2/PPSK SSID) — Howard's decision pending.
- auto_upgrade still OFF (re-enable when ready).

## SAFETY NET (DFS) — follow-up
- UniFi auto-vacates a DFS channel on radar detection (regulatory, automatic) -> a hit moves that one AP,
  not the fleet. 0 vacates observed since apply.
- TODO: stand up a recurring `dfs-check.sh` (fold into the network-logging plan) so we KNOW if radar ever
  fires and can revisit if it does. The DFS sweep so far: 0 genuine radar in the observed window.

## THE LESSON (for me, logged)
Scan/gather ALL the data BEFORE changing anything is the foundation of this plan. I violated it earlier
(applied non-DFS with the survey at 68/74) and wasted a churn cycle. Doing it right — full survey ->
data-driven channel choice -> apply -> validate — produced an actual, measured improvement on the first try.
Data-completeness is a hard gate; no apply until the scan is complete and analyzed.

## Reference
- Survey: .claude/tmp/cascades-survey2.json (74/74). Plan: .claude/tmp/dfs-plan.json. Neighbor: cascades-nbr.json.
- Rollback: dev2.json = full pre-night state (original channels + 80 MHz). Site va6iba3v / 172.16.3.29.
