feat: net-new models + StaticFeed/ArcGIS/Archive clients (Workstream C / PR-2)#2
Merged
Merged
Conversation
…C / PR-2) Completes the spc-cpp v0.1.0 surface. Net-new models (own product-specific severity mappers — do NOT reuse the verbatim categorical severity_from_label): - convective.* — Day4-8 probabilistic + conditional intensity (cig_severity_from_label CIG1..3). - fire_weather.* — fire_severity_from_label ELEV/CRIT/EXTM. - watch.* — IEM spcwatch GeoJSON (TOR/SVR + hail/wind params). - mesoscale.* — MD metadata + geometry ONLY (narrative not parsed). - storm_report.* — IEM LSR Point features. geo/common: - net-new detail::parse_esri_rings, SEPARATE from the verbatim parse_rings. Tuned to MATCH the verbatim outer-ring-only semantics: it drops counter-clockwise Esri hole rings so the Polygon set is parity-exact with the GeoJSON path (the byte-identity gate depends on parse_rings being untouched; this makes the Esri adapter agree with it rather than expose raw Esri shape). - detail::ring_signed_area helper. spc_api clients (Result<T>, pimpl, move-only): - StaticFeedClient (7 static feeds + day4-8), ArcGISClient (primary; ArcGISPager 2000-rec paging; convective queries request f=geojson so the verbatim parser consumes its native shape), ArchiveClient (IEM; conservative RateLimiter + retry). - spc/spc.hpp umbrella expanded to the full surface. Examples + Makefile run-* : parse_outlook, static_feed, arcgis, archive. All three network examples verified against LIVE upstreams (SPC static: 4 cat features; ArcGIS: 4 cat + 4 prob isopleths; IEM: 624 LSRs). Tests: test_arcgis.cpp added — Esri-vs-GeoJSON PIP parity (risk #8) proven probe-for-probe over the live corpus (with a ~5 m skip band because ArcGIS f=json vs f=geojson are independently quantized ~1.3 m apart — documented in the test), plus full net-new model coverage. 23/23 green; clang-format + cpp_auto_audit clean; single glaze::glaze (_deps has exactly one glaze tree).
install(EXPORT ... NAMESPACE spc::) only creates spc::spc for installed find_package(spc) consumers. A FetchContent consumer (e.g. the spc-data refactor in Workstream C / PR-3) only sees the bare 'spc' target and fails 'target spc::spc not found'. Add namespaced ALIAS targets so spc::spc (and spc::spc_*) resolve identically either way — the idiomatic fix matching how the rest of the estate vendors these SDKs. Additive; build + 23/23 ctest still green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Workstream C — PR-2 (spc-cpp full surface)
Completes the
spc-cppv0.1.0 surface on top of PR-1.Net-new product models
Each carries its own product-specific severity mapper — none reuse the verbatim categorical
severity_from_label(different label sets, per the locked decision):convective.*— Day 4-8 probabilistic + conditional intensity (cig_severity_from_labelCIG1..3).fire_weather.*—fire_severity_from_labelELEV/CRIT/EXTM.watch.*— IEMspcwatch(TOR/SVR + hail/wind params).mesoscale.*— MD metadata + geometry only (narrative deliberately NOT parsed).storm_report.*— IEM LSR Point features.Geometry
detail::parse_esri_rings, separate from the verbatimparse_rings. Tuned to match the verbatim outer-ring-only semantics: drops counter-clockwise Esri hole rings so the Polygon set is parity-exact with the GeoJSON path. The verbatimparse_ringsis untouched (byte-identity gate depends on it).Clients (
Result<T>, pimpl, move-only)StaticFeedClient(7 static feeds + day4-8),ArcGISClient(primary;ArcGISPager2000-rec paging; convective queries requestf=geojsonso the verbatim parser gets its native shape),ArchiveClient(IEM; conservativeRateLimiter+ retry).examples/+ Makefilerun-*: parse_outlook / static_feed / arcgis / archive.Verification (live upstreams)
test_arcgis.cpp: Esri-vs-GeoJSON PIP parity (risk #8) proven probe-for-probe over the live corpus. Empirical finding documented in-test: ArcGISf=jsonvsf=geojsonare independently quantized ~1.3 m apart with different vertex sequences, so strict ring equality is impossible by construction; the test asserts identical interior/exterior classification on a dense grid excluding a ~5 m boundary skip-band (a real divergence flips whole regions; quantization does not).clang-format+cpp_auto_auditclean; singleglaze::glaze(_depshas exactly one glaze tree).Merges with a merge commit, then v0.1.0 is tagged (PR-3 FetchContent-pins it). Series: PR-0 ✓ → PR-1 ✓ → PR-2 (this) → PR-3 (spc-data refactor + byte-identity gate).