Fix frontend CII source of truth for on-demand surfaces#4150
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR routes all on-demand CII consumers through server/cached scores before falling back to locally-computed values, and aligns the colour-band thresholds in
Confidence Score: 3/5Safe to merge if the source-switch alert race in checkCIIChanges is accepted or guarded before the next production deployment. The threshold alignment and new accessor helpers are clean and well-tested. The concrete defect is in checkCIIChanges: the module-level previousCIIScores map is not reset when getAuthoritativeCIIScores() switches from locally-computed to backend-cached values, so a cold-start user who exits learning mode before the backend RPC completes will see a round of false CII-spike alerts as soon as the circuit-breaker warms up. src/services/cross-module-integration.ts — specifically the interaction between getAuthoritativeCIIScores() and the previousCIIScores map in checkCIIChanges. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[CII Consumer\ncountry-intel / story-data\nMap / DeckGLMap / military-surge] --> B{getCachedCountryScore\nor getCachedCountryScoreValue}
B -->|cache hit| C[Return backend/cached score]
B -->|cache miss| D[calculateCII local fallback]
E[checkCIIChanges\ncross-module-integration] --> F{getAuthoritativeCIIScores}
F -->|getCachedCountryScores length > 0| G[Backend cached scores]
F -->|empty cache| H[calculateCII local scores]
G --> I[Compare vs previousCIIScores map]
H --> I
I -->|delta ge 10 and not learning| J[Emit CII spike alert]
I --> K[Update previousCIIScores]
L[StrategicRiskPanel.refresh] --> M[fetchCachedRiskScores\ncircuit-breaker]
M -->|data available| N[applyCachedRiskOverview\nbadge = cached]
M -->|null| O[Local overview\nbadge = live or unavailable]
Reviews (1): Last reviewed commit: "fix(frontend): use cached CII scores for..." | Re-trigger Greptile |
| function getAuthoritativeCIIScores(): CountryScore[] { | ||
| const cachedScores = getCachedCountryScores(); | ||
| return cachedScores.length > 0 ? cachedScores : calculateCII(); | ||
| } |
There was a problem hiding this comment.
Spurious CII-spike alerts on cold-start source switch
checkCIIChanges() stores locally-computed CII scores in the module-level previousCIIScores map on the first few calls, before the backend circuit-breaker is warm. Once the backend RPC completes and getAuthoritativeCIIScores() begins returning cached scores, the delta between a locally-computed score (e.g. 5 during early ingestion) and a backend score (e.g. 80) easily exceeds the 10-point threshold, generating a false "CII spike" alert for every affected country in the same checkCIIChanges() call. This only happens on a cold start (no localStorage seed) or after cache expiry, and only when the app is outside learning mode at the moment the circuit-breaker first records a success. A simple guard would be to reset previousCIIScores (or initialise each entry with the new score rather than alerting) whenever the source flips from local to cached.
Summary
Root Cause
Several frontend surfaces still recomputed or preferred local
country-instability.tsscores after server-authoritative CII scores were available, so visible CII-derived values could diverge from the CII panel and choropleth.Validation
npm_config_cache=/tmp/worldmonitor-npm-cache npx tsx --test tests/frontend-cii-source-of-truth.test.mts tests/frontend-cii-closeout.test.mts tests/cached-risk-scores.test.mtsnpm run typecheck