BEACON · NSF NCAR · Design Proposal

The BEACON GUI: a browser-native referee for AI weather models

A ground-up design for BEACON's first product-grade interface — how it stores data, how it computes, and how it lets two very different audiences decide which forecast model is best for them.

Status Draft v0.2 — for review Date 2026-07-09 Governing requirements ux-design-brief.md Distribution Sanitized — no pilot-site identifiers
§0

Contents

  1. Summary — three decisions
  2. What we're building on
  3. Data architecture
  4. Compute & the trust loop
  5. Information architecture & UX
  6. Decision Profiles
  7. Impact Translation
  8. Beyond the brief — MET capabilities
  9. Requirements traceability
  10. Technology choices
  11. Deferred by design
  12. Decisions — resolved and open
§1

Summary — three decisions

BEACON compares AI weather models against conventional numerical weather prediction using standardized METplus verification, entirely in the browser, with no server. Every interface BEACON has had so far — including the current one — was a prototype; this document designs the first product-grade BEACON GUI. The governing design brief asks for something harder than a dashboard refresh: one product that serves a verification scientist and a program manager without betraying either, and that lets a user redefine what “best” means for their mission — honestly.

This proposal rests on three decisions:

Decision 1 — Carry the ingredients, not just the answers The data spine is a single small Parquet file of METplus output that keeps the aggregable line types (contingency-table counts, partial sums) alongside MET's derived statistics. The browser re-derives statistics for any slice with MET-parity math — and checks itself against MET's own numbers. Weighted verdicts become recomputable and provable instead of pre-baked.
Decision 2 — Verdicts are value judgments, and the interface says so The first thing any visitor sees is a ranking under a named Decision Profile — never a naked leaderboard. The active profile, its coverage of the evidence, and its roll-up math stay visible on every verdict. Throughout this document (and the proposed UI), amber marks the places where human priorities, not statistics, are speaking.
Decision 3 — One interface, three vocabularies Instead of an “executive vs. advanced” mode split, every quantity in the product renders in three registers — Plain language, Technical METplus notation, and Impact (cost) framing — behind a single vocabulary lens. Experts and newcomers share one surface, one URL space, and one set of numbers.

Everything else — the tiered store contract, the question-shaped navigation, the honesty gates in the profile roll-up — follows from these three.

§2

What we're building on

Three bodies of prior work were surveyed for this design: the existing BEACON visualization and its prototypes, the MET-AL lab (thirteen browser experiments in modern MET verification), and the metplus-data-store project (a full re-encoding of a real 62 GB verification archive into browser-streamable stores, with parity tests). The new design inherits deliberately — each asset below was adopted, adapted, or declined on its merits.

VerdictAssetWhy
AdoptSingle-file stat Parquet contractThe full 1.53M-row METplus archive fits in one 8.8 MB sorted Parquet, already proven under DuckDB-WASM over HTTP range reads. This is the spine (§3).
AdoptMET-parity math libraryA dependency-free ES-module library (categorical, continuous, vector, ensemble, bootstrap CIs) validated bit-for-bit against 20k+ real MET records, with ratio-of-sums aggregation built in. Becomes the client-side stat engine (§4).
AdoptOracle parity mechanismShip MET's own derived rows next to the ingredients; recompute in the browser; display the match. Turns correctness into a visible trust feature (§4).
AdoptManifest-driven capability flagsThe existing app's manifest pattern, extended: what data exists drives what the UI offers, including honest “not available in this dataset” states (§3, §5).
AdoptDe-identification registry + leak checkRaw archive identifiers never reach the UI; a display-name registry with an automated leak check sanitizes site-identifying strings at build time (§3.4).
AdoptURL-as-state engineeringFull view state — scope, view, profile, lens — serializes to the link. Proven in the current app; extended to carry custom profiles (§6.5).
AdaptPlain↔technical label dictionaryThe current app's two-way translation table grows into a three-vocabulary registry: plain, technical, impact (§5.3).
AdaptPaired-bootstrap significance gridA MET-AL prototype renders head-to-head significance from paired resampling — the statistically correct alternative to eyeballing CI overlap (§4.3, §5).
AdaptMetric / dimension / filter / facet modelA clean interaction vocabulary for cross-filtered exploration; informs the scope bar (§5.2).
DeclineExecutive / Advanced mode toggleNamed prototype residue by the brief. Replaced by the vocabulary lens (§5.3).
DeclinePer-metric weight sliders (0–2)The Arena prototype's take on weighting. Rebuilt as structured Decision Profiles with honesty gates (§6).
DeclineOffline single-file buildsThe MET-AL lab itself pivoted to streaming-first. the BEACON GUI is a hosted product, not an email attachment.
DeclineVirtual-reference / Icechunk storageRejected in the data-store project's own adversarial review: the browser reader can't consume it. Plain Zarr v3 + flat Parquet won.
§3

Data architecture

The brief fixes the platform: browser-only, no backend, potentially slow local queries handled gracefully. The design answers with a tiered static-store contract — every tier is a plain file layout on static hosting, readable via HTTP range requests, and every tier is optional except the first two. The manifest tells the app what it has; the app never guesses.

Build pipeline (offline) METplus archive .stat · pairs · GRIB2 · points Converters + parity tests re-encode, sort, verify vs. original files Sanitizer display-name registry, identifier leak check Static store (R2 / any static host) Tier 0 · manifest.json coverage, spans, capability flags Tier 1 · stats.parquet derived stats + aggregables ~9 MB per campaign, sorted Tier 2 · evidence point obs .parquet (44 MB), matched pairs where emitted Tier 3 · fields.zarr common-grid Zarr v3 — contract reserved, next cycle Tier 4 · objects.parquet MODE/MTD object attributes — contract reserved, next cycle Browser (no backend) UI · state-in-URL views, scope, profile, lens Query worker DuckDB-WASM · SQL over Parquet via HTTP range reads Stat engine MET-parity math: aggregate, derive, bootstrap, normalize Field & object readers zarrita chunks · object SQL — reserved fetch range range
Fig. 1 — System shape. An offline pipeline re-encodes MET output into sanitized static stores; the browser streams only the bytes each question needs. There is no compute backend anywhere — dashed elements are contract-reserved for a later cycle.

3.1 Tier 0 — the manifest

A small JSON document, fetched first, that declares per campaign: the model registry (§3.4), observation sources, variables and levels with their coverage, the valid-time span (the brief's date-filter bound), statistic families present, byte sizes and URLs of every store, and explicit capability flags — for example ensemble: absent in the current archive, which has no probabilistic line types. Capability flags are what let the UI distinguish “this dataset can't answer that yet” from “no data in this slice” (§5.4).

3.2 Tier 1 — the verification spine

One sorted Parquet file per campaign holding the long/tidy METplus stat table: full MET header columns plus line_type, stat_name, stat_value, and confidence bounds where MET emitted them. The surveyed archive proves the scale argument: 1.53 million rows — four models, 24 cycles, twelve variables, six line types — compresses to 8.8 MB, and DuckDB-WASM answers grouped queries against it over HTTP range reads in an existing working demo.

The load-bearing property: the spine keeps the aggregable line types (CTC counts, SL1L2/VL1L2 partial sums) next to the derived ones (CNT, CTS, VCNT). Derived statistics answer “what did MET conclude for this exact slice?”; aggregables let the client honestly recompute statistics for any slice — across cycles, lead windows, or whatever a Decision Profile weights — without committing the mean-of-ratios error (§4.2).

3.3 Tier 2 — evidence for drill-down

The brief's drill-down job says every summary is a path into the evidence behind it. Post-processed statistics dead-end at the aggregate; Tier 2 extends the path. It holds, per campaign: the point-observation table (the surveyed archive's is 11.7 M rows in a 44 MB Parquet — station, position, variable, level, value, QC flag) and matched-pair output — MET's MPR line type, now decided-enabled in the pipeline (§12), landing as its own Parquet table rather than in the spine to protect the spine's size. Matched pairs are what make station-level drill-down and conditional verification (§8) possible. Paired forecast/observed grids also exist in the archive but need a small cataloging pass before browser use. Tier 2 is manifest-gated: when a campaign lacks it, drill-down bottoms out at the source stat rows, honestly labeled.

3.4 Sanitization as an architectural layer

The raw archive contains identifiers that must not reach a public UI — model names and verification masks that encode the pilot site. Sanitization is therefore not an editing pass but a build stage: a display-name registry maps every raw identifier to a public name (e.g., a site-specific baseline renders as “Regional WRF”), and the build fails if any unmapped or forbidden string survives into a published store or bundle. The MET-AL lab already runs exactly this leak check for its public data bundle; the BEACON GUI promotes it to a contract requirement. The UI renders only registry names; provenance panels (§4.4) show registry names too, with raw identifiers available only in non-public builds.

3.5 Deployment: a demo shape now, a production shape later

The app is host-agnostic by construction — any static host with HTTP range support satisfies the contract — so demo and production can differ in origin and freshness without differing in code. Two shapes are designed:

  • Demo (this cycle): Cloudflare, static snapshot. The app deploys to static pages hosting with the Tier 0 manifest and the Tier 1 spine bundled into the deploy itself — at ~9 MB the spine ships same-origin, which eliminates CORS, proxies, and cold-fetch latency in one move. Larger tiers (the 44 MB point-obs table) serve from the existing R2 bucket behind its gating Worker, already live for the sibling lab. The data is explicitly a pinned snapshot: the manifest declares data_mode: "snapshot" with an as-of date, and the UI badges every surface with it, so a demo verdict is never mistaken for a live one.
  • Production (open decision, §12): shape TBD. Today the archive lives on an on-premise server that also hosted the prototype GUI behind Caddy. Caddy serves range requests natively, so the same store contract works there unchanged — with data_mode: "live" and the manifest regenerated as campaigns are processed. Nothing in the app binds to either origin.

The engine runs single-threaded by default, which avoids cross-origin isolation headers entirely; threading is an optional optimization where headers can be set. A failed engine initialization is the one prominent error state (§5.4); a failed individual query degrades to a quiet empty state.

§4

Compute & the trust loop

4.1 Two engines, one contract

DuckDB-WASM (in a Web Worker) does what SQL is good at: slicing the spine by scope, grouping into series, feeding the cascade filters. The stat engine — the adopted MET-parity math library — does what SQL must not be trusted to do: derive verification statistics from aggregables, aggregate across rows correctly, resample for uncertainty, and normalize for profile roll-ups. Queries are keyed by scope and cancellable; a superseded query's results are discarded before render, which is the mechanism behind the brief's no-stale-flicker rule.

4.2 Aggregation correctness

Verification statistics do not average. The RMSE of two days is not the mean of two RMSEs; a hit rate over a month is not the mean of daily hit rates. The only honest aggregation sums the ingredients — contingency counts, partial sums — and derives the statistic once, at the end (ratio of sums, never mean of ratios). Because the spine carries those ingredients, every number in the BEACON GUI that spans more than one MET output row is derived this way, by a library whose aggregation primitives were validated against MET itself.

4.3 Uncertainty and significance

Where MET emitted confidence bounds, the UI shows them. Where a user asks “is this difference real?” the design does not let CI overlap masquerade as the answer — overlapping ranges do not demonstrate equivalence, and the brief flags this as a correctness requirement. Instead, head-to-head significance is computed the way the verification community actually does it: paired resampling on the difference series (both models scored on the same cases, resampled together), rendered as a significance mark with its confidence level. A surveyed MET-AL prototype already implements this grid client-side; the microcopy rule is fixed: “ranges that overlap do not mean the models are equivalent.”

4.4 The trust loop

A referee's authority rests on its arithmetic being checkable. Because the spine carries both ingredients and MET's own conclusions, the client can prove its math on the user's machine, continuously.

MET / METplus the authoritative verification run Derived rows CNT · CTS · VCNT Aggregable rows CTC · SL1L2 · VL1L2 Stat engine re-derives any slice Comparator recomputed vs. MET's own Parity badge recomputed value reference ingredients
Fig. 2 — The trust loop. Every derived number can show its work: the source rows it came from, the formula applied, the aggregation method, and — where MET computed the same statistic — the agreement between the browser's math and MET's. The parity badge is a standing, user-visible self-test.

Concretely, every displayed statistic offers a provenance panel: which stat rows contributed, the derivation (“RMSE from summed squared errors over N pairs”), the aggregation span, and a parity check against MET's derived rows where one exists. This generalizes the “oracle parity” mechanism already prototyped in the surveyed stores — and it is the feature that lets an expert trust a verdict they didn't compute themselves.

§5

Information architecture & UX

5.1 Question-shaped navigation

The brief lists eight jobs-to-be-done and forbids inheriting the old screen structure. The BEACON GUI organizes around the questions users arrive with, in three surfaces plus one overlay:

  • Standing“Which model is doing best — for my needs?” The landing surface: a profile-contextualized verdict, readable with zero terminology (jobs 1, 8).
  • Compare“Where, and by how much?” Skill vs. lead time, head-to-head across variables and levels, and the cross-metric matrix where each measure is judged on its own terms (jobs 2, 3, 4, 5).
  • Evidence“Show me the numbers behind that.” The drill-down terminus: filtered stat tables, series detail, provenance, and — when Tier 2 data exists — station-level observations (job 7).
  • Profile (overlay) — the active Decision Profile: inspect, switch, edit, share (job 8, §6). It is an overlay, not a page, because it contextualizes every surface rather than owning one.

Ensemble calibration (job 6) is designed as a Compare capability that the manifest currently reports absent — it renders as an honest “not available in this dataset” explainer until probabilistic line types arrive (§5.4, §11).

Active Decision Profile — visible on every surface, part of every link Standing verdict under profile, plain-language first, coverage meter, zero setup required Compare skill vs. lead time, head-to-head grid, cross-metric matrix, significance marks Evidence stat rows + provenance, series detail, station observations (when Tier 2 present) drill drill back back Vocabulary lens: Plain · Technical · Impact — one control, all surfaces, carried by the link
Fig. 3 — Three surfaces, one context. Drilling deeper never loses the user's place: scope, profile, and lens persist across surfaces, and “back” returns to the exact prior state (it's all in the URL).

5.2 The scope bar — dependent choices without dead ends

The data's selection dimensions cascade — models constrain observation sources, which constrain variables and levels, and so on — and many combinations simply have no data. The design treats the current selection as a first-class object: a persistent scope bar summarizing model set, observation source, variable, level, statistic, and valid-time range.

  • Unavailable options stay visible, annotated — never silently hidden. An option without data under the current scope renders dimmed with a reason on demand (“no CREDIT runs verified against this source”), so the structure of what exists stays legible.
  • Analysis-fixed dimensions explain themselves in place. When a view fixes a dimension (vector-wind verification implies vector statistics), the scope bar shows that segment as set by the analysis, with one line of why — a consequence, not a lockout.
  • Date controls operate on forecast valid time, bounded by the manifest's actual span, with the bound shown.

5.3 Three vocabularies, one lens

Every quantity in the product has three registered renderings, from one translation registry:

LensSame quantity, renderedPrimary audience
Plain“Typical 2-meter temperature error, in degrees”Decision-makers, newcomers
TechnicalTMP Z2 · RMSE (K) — exact METplus notation, never paraphrasedVerification scientists, model developers
Impact“≈ $12k–$40k per event at stake” — estimate, assumptions attached (§7)Program managers, planners

The lens is a single global control. Plain is the default for a first visit; the chosen lens rides in the URL, so a shared link reproduces not just the data view but the register it was read in. Crucially the lens is per-rendering, not per-mode: hovering (or focusing) any labeled quantity reveals its other two renderings, so an expert reading Plain-language output can always see the exact notation underneath, and a newcomer in Technical view is one gesture from an explanation. Nobody is trapped in a mode that wasn't built for them — this replaces the executive/advanced split.

5.4 The three states, and the one loud error

Every data region distinguishes, visibly and textually:

  • Loading — a quiet skeleton in the region's final geometry; no spinners over stale content, and superseded results never flash (§4.1).
  • No data for this selection — a designed empty state that names the narrowing choice (“Nothing verified for this variable in March. Try widening the date range”), because empty is a normal property of sparse verification data, not a failure.
  • Capability unavailable — manifest-driven: “This dataset contains no ensemble output, so calibration can't be assessed. Here's what that would show.” The surface stays discoverable and self-explaining rather than disappearing.

One error is deliberately loud: the data engine failing to initialize, which blocks everything and says so plainly. Any single failed query degrades to the quiet empty state.

5.5 The Standing surface, sketched

Profile: General (balanced) ▾ Lens: ● Plain ○ Technical ○ Impact Scope: 4 models · Jun 1–6 ▾ Under the General profile, AIGFS leads this evaluation period — strongest on temperature and pressure; GFS stays closer on wind. A ranking reflects the priorities of the active profile. It is a judgment, not a measurement. See how it's computed ↗ Standing under this profile AIGFS GFS Regional WRF CREDIT Bars: profile-weighted standing (0–1, this profile's normalization). Whiskers: resampling range. Overlapping whiskers do not mean the models are equivalent. Evidence coverage: 91% Weighted but missing: wind gusts (not verified) Where AIGFS wins ↗ by variable · by lead time → Compare, scope carried
Fig. 4 — Standing, wireframe. A first-time visitor gets a complete, honest answer with zero configuration: a plain sentence, a ranked view with uncertainty, the profile that produced it (amber — a judgment), how much evidence backs it, and a path into the detail. Model names shown are display-registry names on real archive data.

5.6 Cross-cutting: brand, access, small screens, onboarding

  • Brand. NSF NCAR identity applied through a token layer (type, color, wave motifs where restrained) — reviewed against the brand toolkit rather than improvised. The one systematic extension: amber is reserved product-wide for value-judgment context, so brand color and epistemic meaning never collide.
  • Accessibility. WCAG AA as an acceptance gate: full keyboard operability (the scope bar, lens, and profile editor are the hard cases and get explicit keyboard specs), visible focus, ARIA landmarks per surface, chart data reachable as tables, reduced-motion honored (state transitions become instant swaps).
  • Responsive. Dense comparison grids don't shrink — they re-rank: on narrow viewports the head-to-head grid becomes a sorted list of the largest honest differences with the full grid one tap away. The scope bar collapses to a summary chip that opens a full-screen editor.
  • Onboarding. The Standing surface is the onboarding: it teaches profile, uncertainty, and drill-down by being read. First-visit affordances are limited to three dismissible, non-blocking anchors (what a profile is, what the whiskers mean, where the evidence lives).
§6

Decision Profiles

The brief's central truth: “best” is not absolute. A Decision Profile captures a use case's priorities and rolls verification evidence into a standing under those priorities — transparently, recomputably, and labeled as the value judgment it is.

6.1 What a profile is

A small, serializable object — not a UI arrangement:

  • Identity: name, one-sentence description of who it's for.
  • Priorities: weights over outcome facets — variable groups (temperature, wind, precipitation, pressure), lead-time windows (nowcast, day-one, medium-range), verification regions (where accuracy matters most — MET's masking regions, §8), and statistic families (systematic error, random error, event detection) — not over 86 raw statistics. Facets keep weights meaningful to a non-expert and map deterministically onto stat rows for the engine.
  • Roll-up method: the normalization and blend used to make facets comparable (§6.3) — named and inspectable, never implicit.
  • Optionally, a cost model (§7), so Impact Translation travels with the profile.

6.2 Presets, default, custom

Preset candidates below come from research on thirty weather-dependent professional cohorts; the catalogue and every weight in it are content to be set with domain experts. Decision (§12): presets ship draft-labeled — marked draft in-product until expert review, rather than waiting on it. General (balanced) is the clearly-labeled default, active from first paint so a visitor gets a coherent answer with zero configuration. One preset is not a draft: MET's own reference skill-score index (§8), whose weights are fixed by the verification community and double as a calibration target for the roll-up engine.

PresetLeans towardExample cohorts served
General (balanced) — defaultEven facet weights; every family judged on its own termsFirst visit, program overview
Severe weather & emergency mgmt.Event detection, precipitation extremes, day-one leadsEmergency managers, response planners
Wind energyNear-surface wind speed/direction, short leads, random errorFarm operators, grid load forecasters
Aviation operationsWind aloft, visibility/ceiling family, nowcast-to-day-oneDispatch, flight planning
Agriculture & waterTemperature extremes, precipitation totals, medium-rangeGrowers, reservoir operations
Reference skill index (MET)MET's published skill-score-index weighting, unmodified — a community-defined composite, not a BEACON judgmentVerification scientists; doubles as the roll-up engine's parity target (§8)

6.3 The roll-up, with honesty gates

1 · Slice stat rows per facet, current scope 2 · Aggregate sum ingredients, derive once 3 · Normalize relative standing 0–1, per facet, per direction 4 · Weight the profile speaks — a value judgment 5 · Verdict standing + coverage + resampling range empty facets recorded, never imputed ratio of sums — never mean of ratios direction gate: lower-is- better inverts before blend weights shown with verdict, always withheld if coverage falls below floor Every stage is inspectable from the verdict's “how this was computed” panel: facet table, aggregation spans, normalization values, weights, coverage.
Fig. 5 — The roll-up pipeline. Stages 1–3 are statistics; stage 4 — and only stage 4 — is human priorities, marked amber here and in the product. The gates beneath each stage are correctness requirements from the brief, engineered as invariants rather than review notes.

Normalization (stage 3) makes non-comparable measures blendable, so it must be inspectable, not a black box. The proposed default: within each facet, each model's aggregated statistic maps to a relative standing on 0–1 against the model field in the current scope, after applying the metric's direction (a data property — reducing a lower-is-better error always reads as improvement). The method is named in the UI, its intermediate values are visible in the “how this was computed” panel, and the architecture treats it as a pluggable strategy so domain experts can evaluate alternatives (e.g., skill-score-referenced scaling) without a redesign.

6.4 Honest degradation

Sparse data meets weighted priorities constantly, and the brief demands the collision be visible. Three mechanisms:

  • Coverage meter on every verdict: the share of the profile's weighted evidence actually present in scope, with the missing facets named (“wind gusts: weighted 20%, not verified in this dataset”).
  • No silent renormalization. Missing weight is reported as missing; the verdict never quietly pretends the profile was different from what the user chose.
  • A verdict floor. Below a coverage threshold the standing is withheld — “not enough of what this profile values has been verified here” — because an honest refusal beats a confident distortion.

6.5 Custom profiles, two depths, one object

One capability, two editors over the same object — neither audience gets a dumbed-down or gated-off version:

  • Guided: plain-language importance choices (“matters most / matters / doesn't matter”) over outcome facets, phrased as outcomes (“catching rare severe events”, “getting tomorrow's wind right”). Three decisions produce a legitimate profile.
  • Precise: numeric facet weights, statistic-family selection within facets, normalization strategy, coverage floor. Switching depths never loses state — Guided choices are coarse positions of the same weights Precise exposes.

The active profile — preset or custom — serializes compactly into the URL. A colleague opening a shared link sees the same verdict under the same priorities, with the same amber context. Named presets travel by id; custom profiles travel by value; server-side persistence stays out of scope per the brief.

§7

Impact Translation

Impact Translation re-expresses skill differences in consequences — above all money — so a decision-maker can grasp what a difference in accuracy is worth. It is engineered as the third vocabulary (§5.3): an optional lens over the same quantities, never a replacement for them.

The cost model is a visible object. Each translation rests on a named cost model attached to the profile: an exposure unit (“per event”, “per operating day”), parameters (“imbalance penalty $/MWh”, “cost of an unnecessary protective action”), a mapping from error statistics to expected cost, and a source note for every parameter. Choosing the Impact lens opens with the assumptions, not just the number.

Defaults are illustrations, and say so. No supplier of validated cost parameters exists yet (decision, §12), so v1 ships illustrative defaults: order-of-magnitude parameter sets per preset, sourced from public literature where possible, every one user-adjustable in place. The framing is fixed accordingly — figures are labeled Illustrative estimate — theoretical, based on adjustable assumptions, the assumptions drawer opens on first use of the lens, and the disclaimer travels with shared links. The lens's honest job at this stage is to teach how skill converts to consequence and let users bring their own numbers — not to assert what anything costs.

Ranges, labels, and challengeability. Figures render as ranges (parameter bounds propagated through the mapping). Parameter edits recompute live and travel with the shared profile — turning a suspicious number into a sensitivity analysis. The technical rendering of the underlying statistic stays one gesture away, so an expert can always interrogate the conversion. A confidently wrong dollar figure is the failure mode this section exists to prevent; when a profile has no cost model, the Impact lens says exactly that instead of improvising one.

§8

Beyond the brief — MET capabilities worth adopting

The brief describes the product; MET describes what verification can honestly say. Several MET/METplus capabilities the brief never mentions bear directly on its central goal — fair, use-case-specific, region-specific comparison — and most cost little to adopt because they arrive as new rows in the existing store contract, not new architecture. Two deserve the headline:

Fairness across model resolutions is a MET capability, not a UI nicety. Point-to-point scoring double-penalizes a high-resolution model — a storm predicted correctly but displaced one grid cell scores worse than no storm at all — which systematically flatters coarse global models in exactly the comparisons BEACON exists to referee. MET's neighborhood methods (fractions skill score) and station-neighborhood analogue (HiRA) are the community's answer, and a referee comparing 2.5 km regional baselines against 0.25° global AI models should adopt them.

MET already ships a weighted composite — use it as the profiles' anchor. MET's skill-score index (the GO-Index family) is a community-defined weighted blend of skill scores across variables, levels, and leads. It is precedent that weighted composites are legitimate verification practice, a shipped preset whose weights BEACON did not choose, and — because MET can compute it offline — an end-to-end parity target for the entire profile roll-up engine, extending the trust loop (§4.4) from individual statistics to the composite itself.

MET capabilityWhy it serves honest comparisonHow it landsWhen
Verification regions (masks)“Best” differs by region as much as by use case; region-conditioned verdicts answer real questionsRegion becomes a scope dimension and a profile facet axis (§6.1); spine rows already carry the mask columnNow — data present
Skill-score index (GO-Index family)Community-sanctioned weighted composite; calibrates the roll-up engine“Reference skill index” preset (§6.2) + composite-level parity checkNow — offline job feeds reference values
Neighborhood skill (FSS)Scale-aware scoring; removes the double penalty that flatters coarse modelsNew line types in the Tier 1 spine; Compare gains a spatial-scale control where presentPipeline config
HiRA (station neighborhoods)The point-verification analogue of FSS; fair to high-res models at stationsNew line types in the spinePipeline config
Percentile thresholdsDefines “events” against each model's own climatology, removing systematic-bias advantage in event detectionPipeline config; threshold provenance in the manifestPipeline config
Climatology-anchored scores (anomaly correlation)The headline metric of the AI-weather literature; enables like-for-like comparison with published resultsAnomaly statistics in the spine once climatology fields join the pipelinePipeline config
Ramp-event verificationScores catching rapid changes — wind ramps, temperature swings — precisely what several profiles value mostRamp contingency rows feed the event-detection facetPipeline config
Conditional verification on matched pairs“How does it do when it actually rains” — stratify by observed conditions, station, or time of dayTier 2 MPR Parquet (§3.3) + client-side stat jobsNext campaign — MPR enabled (§12)
Object-based verification (MODE/MTD)Decomposes error into displacement, size, intensity, timing — a plain-language error vocabulary (“right storm, wrong place”)Tier 4 — object & event tables: Parquet of object attributes and matched pairs (Fig. 1); a browser MODE engine already exists in the surveyed labNext cycle

Only the last row adds a tier; everything else is new rows in existing stores plus facet vocabulary. None of it adds screens — Compare and Evidence absorb these as dimensions and drill-downs, and the scope bar's capability-awareness (§5.4) keeps absent ones honest. This is deliberate: adopting more of MET must deepen the referee, not sprawl the product.

§9

Requirements traceability

The brief's appendix defines the review test: every “must honor” item satisfied, by mechanisms this document can point to.

Must honor (brief)Mechanism here
Two audiences, both first-classVocabulary lens + per-element register reveal (§5.3); no mode split
Eight jobs achievableStanding / Compare / Evidence surfaces + Profile overlay (§5.1); ensemble job manifest-gated (§5.4)
Non-expert first encounter, no terminologyStanding: plain verdict sentence, default profile, zero setup (§5.5)
Cascade dependencies feel coherentScope bar; unavailable options annotated, not hidden (§5.2)
Empty results read as normalDesigned no-data state naming the narrowing choice (§5.4)
Analysis-fixed dimensions self-explain“Set by the analysis” scope segments with inline why (§5.2)
Metric direction is a data propertyDirection gate in normalization; no user toggle anywhere (§6.3)
CI overlap must not imply equivalencePaired-difference significance; fixed microcopy (§4.3)
Valid-time date filtering, boundedManifest spans drive date controls (§3.1, §5.2)
Cross-metric summary judges each measure on its own termsPer-facet normalization; matrix cells never share a scale (§5.1, §6.3)
Presets + labeled default + custom profiles§6.2, §6.5; weights set with domain experts, draft-labeled until then
Weighted ranking reads as value judgmentAmber convention, always-visible profile chip, “how computed” panel (§5.5, §6.3)
Roll-up preserves direction; normalization inspectableHonesty gates 3–4; pluggable, named normalization (§6.3)
Honest degradation under sparse dataCoverage meter, no silent renormalization, verdict floor (§6.4)
Profile in shareable statePreset by id, custom by value, in the URL (§6.5)
Cost assumptions visible; estimates labeledCost model as visible object; ranges; in-place edit (§7)
Impact optional; native stats reachableLens, not mode; technical rendering one gesture away (§5.3, §7)
Browser-only; graceful loading; no stale flickerStatic tiers (§3); keyed, cancellable queries (§4.1); skeletons (§5.4)
Loading / no-data / unavailable distinguishableThree designed states, manifest-driven third state (§5.4)
Engine failure loud; single query quiet§3.5, §5.4
Shareable URL for full view stateScope + view + profile + lens serialization (§5.1, §6.5)
NSF NCAR brand; WCAG AA; responsiveToken layer; acceptance-gate accessibility; re-rank-don't-shrink (§5.6)
Out-of-scope items not designed aroundTiers 3–4 reserved as contract only; roadmap isolated (§11)
§10

Technology choices

Every predecessor was a prototype, so continuity with prior code carries no weight here — each layer is chosen on current merits among modern, open-source options. The load-bearing fact: the data layer (stores, worker, stat engine) is framework-agnostic by construction, so the UI-framework choice is deliberately the most reversible one on this list.

LayerRecommendationRationale / alternative considered
Language & buildTypeScript + ViteTyped contracts end-to-end (manifest, profile object, query results); Vite is the current open-source standard for SPA tooling.
UI frameworkSvelte 5Compiled, fine-grained reactivity drives the bespoke SVG encodings (verdict bars, significance grid, coverage meter) without virtual-DOM overhead; small bundles suit a browser-only data app; accessible headless primitives via Bits UI. React 19 + React Aria considered: the deepest accessibility-component ecosystem — the right call if complex-widget a11y is weighted above leanness. Either satisfies the design; the architecture doesn't care.
Query engineDuckDB-WASM (Web Worker, single-thread default)Proven twice against this exact Parquet contract; single-thread avoids isolation-header constraints (§3.5).
Verification mathVendor the MET-parity library as a typed packageDependency-free ES modules with self-tests; framework-agnostic; parity pedigree is the point (§4). Wrap, don't rewrite.
Async/stateURL as source of truth; TanStack Query (framework adapters for both candidates) over the workerKeyed caching + cancellation gives the no-stale-flicker guarantee near-free (§4.1).
ChartsObservable Plot + bespoke SVG componentsPlot for statistical series (already proven on this data); bespoke SVG where honesty encodings are the design (verdict bars, significance grid, coverage meter). ECharts considered: capable but heavier, and canvas internals resist the fine-grained a11y and encoding control the signature views need.
StylingDesign-token CSS layer (custom properties), NSF NCAR brand tokensTokens are the brand + amber-convention enforcement point (§5.6).
TestingVitest + Playwright + stat-parity suite in CIThe parity suite (client math vs. MET derived rows, on real sanitized fixtures) is the referee's regression test.
Fields (Tier 3, reserved)zarrita.js when the cycle opensProven against these stores; nothing to build now (§11).
§11

Deferred by design

Excluded from this cycle by the brief, but the architecture leaves each a clean socket rather than a rework:

  • Ensemble calibration — the Compare surface reserves it; the manifest's capability flag flips it on the day probabilistic line types (ECNT, RHIST, PCT) appear in a campaign. No redesign, new data.
  • Spatial verification maps — Tier 3's common-grid Zarr contract exists and is already built upstream; forecast/analysis/error fields become an Evidence extension in a future cycle.
  • Interactive thresholds — recomputing categorical skill live from paired fields (the “oracle” pattern, already prototyped) belongs to the same future cycle as fields.
  • Station time series & conditional verification — no longer deferred by decision, only by data: MPR emission is enabled (§12), and the Evidence surface receives it as soon as the next campaign is processed (§3.3, §8).
  • Object-based verification (MODE/MTD) — Tier 4's object tables (§8); a validated browser MODE engine already exists in the surveyed lab when the cycle opens.
  • Reliability diagrams, rank histograms, dark mode, image export — out of scope per the brief; nothing here depends on their absence.
§12

Decisions — resolved and open

Resolved with the product owner, 2026-07-09:

DecisionResolution
Product & repo nameBEACON GUI (repo: beacon-gui). Every predecessor — including the current visualization — was a prototype; this is BEACON's first product-grade interface, and the name says so rather than implying an evolution of something never released.
Preset shippingShip draft-labeled (§6.2). The expert weighting session still happens; it just doesn't block launch.
Cost modelsIllustrative, user-adjustable defaults with prominent theoretical-estimate disclaimers (§7). No parameter supplier exists yet; the lens teaches the conversion and invites the user's own numbers.
Matched-pair emissionEnabled. MPR output lands as Parquet in Tier 2 (§3.3) — same engine, same contract as the rest of the stores.
Demo deploymentCloudflare static-snapshot demo (§3.5): spine + manifest bundled with the deploy, larger tiers from the existing R2 bucket, data_mode: "snapshot" badged in the UI.
Brand application reviewConfirmed: token layer reviewed against the NSF NCAR brand toolkit before visual build-out (§5.6).

Still open:

DecisionNotes
Production deployment shapeData and processing live on an on-premise server today (Caddy served the prototype). The store contract runs unchanged there or on object storage; decision deferred until production planning (§3.5).
Normalization defaultRelative standing (proposed) vs. skill-score-referenced scaling (§6.3). The pluggable design defers this safely — and the MET reference index (§8) now provides a community-defined anchor to evaluate candidates against.
Preset weights sessionScheduling the domain-expert review that graduates presets out of draft (§6.2).