mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
* feat(supply-chain): Sprint E — scenario visual completion + service parity - E1: fetchSectorDependency exported from supply-chain service index - E2: PRO gate + all-renderer dispatch in MapContainer.activateScenario - E3: scenario summary banner in SupplyChainPanel (dismiss wired) - E4: "Simulate Closure" trigger button in expanded chokepoint cards - E5: affectedIso2s heat layer in DeckGLMap (GeoJsonLayer, red tint) - E6: SVG renderer setScenarioState (best-effort iso2 fill) - E7: Globe renderer scenario polygons via flushPolygons - E8: integration tests for scenario run/status endpoints * fix(supply-chain): address PR #2910 review findings (P1 + P2 + P3) - Wire setOnScenarioActivate + setOnDismissScenario in panel-layout.ts (todo #155) - Rename shadow variable t→tmpl in SCENARIO_TEMPLATES.find (todo #152) - Add statusResp.ok guard in scenario polling loop (todo #153) - Replace status.result! non-null assertion with shape guard (todo #154) - Add AbortController to prevent concurrent polling races (todo #162) - Add polygonStrokeColor scenario branch (transparent) in GlobeMap (todo #156) - Re-export SCENARIO_TEMPLATES via src/config/scenario-templates.ts (todo #157) - Cache affectedIso2Set in DeckGLMap.setScenarioState (todo #158) - Add scenario paths to PREMIUM_RPC_PATHS for auth injection (todo #160) - Show template name in scenario banner instead of raw ID (todo #163) * fix(supply-chain): address PR #2910 review findings - Add auth headers to scenario fetch calls in SupplyChainPanel - Reset button state on scenario dismiss - Poll status immediately on first iteration (no 2s delay) - Pre-compute scenario polygons in GlobeMap.setScenarioState - Use scenarioId for DeckGL updateTriggers precision * fix(supply-chain): wire panel instance to MapContainer, stop button click propagation - Call setSupplyChainPanel() in panel-layout.ts so scenario banner renders - Add stopPropagation() to Simulate Closure button to prevent card collapse
2.4 KiB
2.4 KiB
status, priority, issue_id, tags, dependencies
| status | priority | issue_id | tags | dependencies | |||||
|---|---|---|---|---|---|---|---|---|---|
| complete | p1 | 154 |
|
|
Non-Null Assertion on Optional result Without Guard in Polling Loop
Problem Statement
In SupplyChainPanel.ts:679, result = status.result! uses a non-null assertion on a field typed as optional. If the server sends { status: 'done' } without result (version mismatch or worker bug), undefined is silently passed to onScenarioActivate, which crashes in activateScenario when it calls result.topImpactCountries.map(...). Additionally, impactPct * 100 in showScenarioSummary could produce NaN if the upstream type changes (prior art: feedback_pizzint_spike_magnitude_type.md).
Findings
- File:
src/components/SupplyChainPanel.ts, line 679 - Code:
if (status.status === 'done') { result = status.result!; break; } status.resultis typed as optional (result?: ScenarioResult)- If
status.resultis absent,undefinedpropagates toactivateScenario→ crash intopImpactCountries.map(...) impactPctis numeric but upstream could change to string (see MEMORY:feedback_pizzint_spike_magnitude_type.md)
Proposed Solutions
Option A: Explicit guard + type narrowing (Recommended)
if (status.status === 'done') {
const r = status.result;
if (!r || !Array.isArray(r.topImpactCountries)) throw new Error('done without valid result');
result = r;
break;
}
Pros: Explicit, catches server bugs, type-safe without !
Cons: Slight verbosity
Effort: Small | Risk: None
Option B: Minimal guard only
if (status.status === 'done') {
if (!status.result) throw new Error('done without result');
result = status.result;
break;
}
Protects against undefined but not malformed topImpactCountries.
Effort: Small | Risk: Low
Recommended Action
Apply Option A — adds one guard line, eliminates the ! assertion.
Technical Details
- Affected files:
src/components/SupplyChainPanel.ts - Lines: 679
Acceptance Criteria
- Non-null assertion
!removed fromstatus.result topImpactCountriespresence verified before usenpm run typecheckpasses without!assertion
Work Log
- 2026-04-10: Identified by kieran-typescript-reviewer during PR #2910 review
Resources
- PR: #2910
- MEMORY:
feedback_pizzint_spike_magnitude_type.md