From c66af5bf649648afb39030f5a358535840205ad8 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 1 Aug 2026 16:34:56 -0500 Subject: [PATCH] fix(recalibrate): correct stale "documentation only" report text, map 9cm band Two defects surfaced by the 2026-08-01 production run. The generated report's "Applying these weights" section claimed the JSON was inert until someone wired it into BandConfig. That stopped being true when BandWeights landed: BandConfig.weights/1 consults BandWeights.lookup/1 ahead of the in-source :weights override and the global @weights default, so band_weights.json is a live scoring input. Anyone reading the report would have concluded a recalibration run was a no-op. Replace the paragraph and document the operational half that was missing entirely -- BandWeights caches into :persistent_term on first read, so a running node serves the previous weights until it is redeployed or BandWeights.reset/0 is called. PSKR_BAND_TO_MHZ was missing 9cm, so every run logged "skipping unknown PSKR band" and dropped those rows from the corpus accounting. Weight derivation is unaffected -- 3400 MHz is not in PSKR_BANDS, so it still routes to the contacts fit (source=contacts, n=334, unchanged). The dict already carries other non-routed bands (23cm, 13cm, 3cm); 9cm was simply absent. --- scripts/recalibrate.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/scripts/recalibrate.py b/scripts/recalibrate.py index cdcadcaa..5d2bb680 100755 --- a/scripts/recalibrate.py +++ b/scripts/recalibrate.py @@ -134,6 +134,7 @@ PSKR_BAND_TO_MHZ: dict[str, int] = { "70cm": 432, "23cm": 1_296, "13cm": 2_304, + "9cm": 3_400, "3cm": 10_000, } @@ -519,12 +520,19 @@ def render_report( # ── How to apply lines.append("## Applying these weights\n") lines.append( - "This script writes `priv/algo/band_weights.json` and stops " - "there — it never edits `band_config.ex`. To make the weights " - "live, `BandConfig.weights(band_mhz)` needs a one-time edit to " - "read this JSON at app start (cache in `:persistent_term`) and " - "merge `band_overrides[band].weights` over the in-source " - "defaults. Until then, the JSON is documentation only." + "These weights are **live scoring inputs, not documentation**. " + "`BandConfig.weights/1` consults `BandWeights.lookup/1` (which " + "reads this JSON) *before* falling back to the in-source " + "`:weights` override or the global `@weights` default. This " + "script still never edits `band_config.ex` — it only rewrites " + "the JSON.\n" + ) + lines.append( + "`BandWeights` caches the parsed file in `:persistent_term` on " + "first read, so a running node keeps serving the *previous* " + "weights until it restarts. To put this run into effect, deploy " + "(the file ships under `priv/`) or call `BandWeights.reset/0` on " + "every node." ) return "\n".join(lines)