Skip to content

feat(variant): Energy Atlas — Release 1 Day 1 (variant scaffolding)#3291

Merged
koala73 merged 6 commits into
mainfrom
feat/energy-atlas-release-1
Apr 22, 2026
Merged

feat(variant): Energy Atlas — Release 1 Day 1 (variant scaffolding)#3291
koala73 merged 6 commits into
mainfrom
feat/energy-atlas-release-1

Conversation

@koala73

@koala73 koala73 commented Apr 22, 2026

Copy link
Copy Markdown
Owner

Summary

Day 1 of the Energy Atlas Release 1 plan. Introduces the energy variant scaffolding so subsequent PRs on this branch can build the pipeline registry, storage registry, shortage classifier, and disruption log against a real variant surface.

See the internal plan (not committed — gitignored in docs/internal/) for the full 4-week schedule, scope, and Release 1 vs Release 2 split.

What this PR adds

  • src/config/variants/energy.ts — new variant config, modeled on commodity.ts
    • DEFAULT_PANELS enables existing energy-adjacent panels: energy-complex, oil-inventories, hormuz, energy-crisis, fuel-prices, renewable-energy, commodities (WTI/Brent/NatGas), supply-chain (chokepoints), sanctions-pressure, gulf-economies, climate, plus map and live-news.
    • DEFAULT_MAP_LAYERS enables pipelines, waterways (chokepoints), AIS (tanker positions), commodityPorts (LNG + crude terminals), minerals (energy-transition overlap), commodityHubs, sanctions, climate, outages, natural, weather, fires, tradeRoutes. Every geopolitical / military / tech / finance / happy variant layer explicitly false per multi-variant-site-data-isolation skill.
    • MOBILE_DEFAULT_MAP_LAYERS — minimal mobile set (pipelines, waterways, commodityPorts, natural).

What this PR does NOT add (coming in subsequent PRs on this branch)

  • Pipeline registry (curated ~75 gas + ~75 oil) + PipelineStatusPanel
  • Storage facility registry (curated ~125 facilities) + StorageFacilityMapPanel
  • Fuel shortage classifier + FuelShortagePanel (automated watch + evidence-threshold-gated confirmed)
  • Pipeline/storage disruption event log
  • Country drill-down Energy section on CountryDeepDivePanel
  • Atlas landing composition at variant root
  • Vercel domain alias for energy.worldmonitor.app (infra, not code)

Release 2 (post-launch, not on this branch)

Scenario runner, getEnergyShock cascade RPC, 5 MCP tools, Clerk subscription model, global tanker density, shadow-fleet overlay.

Test plan

  • Typecheck passes (npm run typecheck)
  • All 175 pre-push tests pass
  • Unicode safety pre-commit hook clean
  • Variant smoke-test locally by setting VITE_VARIANT=energy and verifying the listed panels render without error
  • Confirm no geopolitical / military / tech layer bleeds into the energy variant build (multi-variant-site-data-isolation)
  • Follow-up PRs add actual asset data; this PR is the shell only

Conventions followed

  • worldmonitor-pro-panel-gating — variant is free-tier; no PRO gating introduced here
  • multi-variant-site-data-isolation — explicit per-layer toggle matches commodity/finance variant pattern
  • feedback_world_coverage_never_subset.md — future asset registries will be curated-critical for launch (~75/75/125) then expand; no MAJOR_REPORTERS-style hardcoded subset
  • No --no-verify; pre-commit + pre-push hooks ran cleanly

….app

Release 1 Day 1 of the Energy Atlas plan — introduces src/config/variants/energy.ts
modeled on the commodity variant. No new panels or RPCs yet; the variant reuses
existing energy-related panels (energy-complex, oil-inventories, hormuz,
energy-crisis, fuel-prices, renewable-energy) + supply-chain/sanctions context.

Map layers enable pipelines, waterways, AIS, commodityPorts, minerals, climate,
outages, natural, weather. All geopolitical/military/tech/finance/happy variant
layers explicitly disabled per variant isolation conventions.

Next PRs on feat/energy-atlas-release-1 add:
- Pipeline & storage registries (curated critical assets, ~75 gas / ~75 oil / ~125 storage)
- Global fuel-shortage registry with automated evidence-threshold promotion
- Pipeline/storage disruption event log
- Country drill-down Energy section
- Atlas landing composition at variant root
@vercel

vercel Bot commented Apr 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldmonitor Ready Ready Preview, Comment Apr 22, 2026 0:45am

Request Review

…sition

Day 2 of the Energy Atlas Release 1 plan. The Day-1 commit added a canonical
variants/energy.ts but discovery during Day 2 showed the app's runtime variant
resolution lives in src/config/panels.ts (ENERGY_PANELS/ENERGY_MAP_LAYERS/etc.),
not in variants/*.ts (which are orphans). This commit does the real wiring.

Changes:
- src/config/panels.ts — ENERGY_PANELS, ENERGY_MAP_LAYERS, ENERGY_MOBILE_MAP_LAYERS;
  registered in ALL_PANELS, VARIANT_DEFAULTS, VARIANT_PANEL_OVERRIDES; wired into
  DEFAULT_MAP_LAYERS + MOBILE_DEFAULT_MAP_LAYERS ternaries. Panels at launch:
  map, live-news, insights, energy-complex, oil-inventories, hormuz, energy-crisis,
  fuel-prices, renewable-energy, commodities, energy (news), macro-signals,
  supply-chain, sanctions-pressure, gulf-economies, gcc-investments, climate,
  monitors, world-clock, latest-brief.
- src/config/variant.ts — recognize 'energy' as allowed SITE_VARIANT; resolve
  energy.worldmonitor.app subdomain to 'energy'; honor localStorage override.
- src/config/variant-meta.ts — SEO entry for energy.worldmonitor.app (title,
  description, keywords targeting 'oil pipeline tracker', 'gas storage map',
  'fuel shortage tracker', 'chokepoint monitor', etc.).
- src/app/panel-layout.ts — desktop variant switcher + mobile menu both list
  energy with ⚡ icon and t('header.energy') label.
- src/App.ts + src/app/data-loader.ts — energy variant enables trade-policy and
  supply-chain data loads (chokepoint exposure is a core Atlas surface).
- src/app/data-loader.ts — daily-brief newsCategories override for energy variant
  (energy, energy-markets, oil-gas-news, pipeline-news, lng-news).
- src/locales/en.json — 'header.energy' translation key.
- src/config/variants/energy.ts — add clarifying comment that real wiring lives
  in panels.ts (same orphan pattern as commodity.ts/finance.ts/etc.).

Atlas landing composition: the variant now renders its energy panel set with
energy-specific names (Energy Atlas Map, Energy Headlines, AI Energy Insights)
when SITE_VARIANT === 'energy'. Pipeline and commodity-port map layers enabled
so Week 2's pipeline registry + storage-facility registry drop in with layers
already toggled on.

Typecheck clean; 175 pre-push tests expected to remain green.

Subsequent PRs on feat/energy-atlas-release-1:
- Week 2: pipeline registry + storage facility registry (evidence-based)
- Week 3: fuel-shortage classifier + disruption log + country drill-down
- Week 4: automated revision log, SEO polish, launch
koala73 added 2 commits April 22, 2026 15:31
Day 3 of the Energy Atlas Release 1 plan. Adds ChokepointStripPanel — a
compact horizontal strip of chip-style cards, one per chokepoint, showing
name + status color + flow-as-%-of-baseline + active-warnings badge.
Ordered by volume: Hormuz, Malacca, Suez, Bab el-Mandeb, Turkish Straits,
Danish Straits, Panama.

GEF covers 5 chokepoints (Hormuz, Malacca, Suez, Bab el-Mandeb, Panama).
We cover 7 — adds Turkish Straits + Danish Straits. One of the surpass
vectors enumerated in §5.7 of the plan doc.

Data: reuses the existing fetchChokepointStatus() RPC backed by
supply_chain:chokepoints:v4 (Portwatch DWT + AIS calibration). No new
backend work; this is pure UI composition.

Changes:
- src/components/ChokepointStripPanel.ts — new Panel subclass with
  in-line CSS for the chip strip; falls back gracefully when a chokepoint
  is missing from the response or FlowEstimate is absent.
- src/components/index.ts — barrel export.
- src/app/panel-layout.ts — import + createPanel registration near
  existing energy panels.
- src/config/panels.ts — ENERGY_PANELS adds 'chokepoint-strip' at priority 1
  (renders near top of atlas). Also fixes two panel-ID mismatches caught
  while wiring: 'hormuz' → 'hormuz-tracker' and 'renewable-energy' →
  'renewable' (matches HormuzPanel.ts and RenewableEnergyPanel registration).

Typecheck clean. No new tests required — panel renders real data.
Days 4 & 5 of the Energy Atlas Release 1 plan.

## Day 4 — Attribution footer (src/utils/attribution-footer.ts)

A reusable string-builder that stamps every energy-atlas number with its
provenance. Design intent per plan §5.6 (quantitative rigour moat):
"every flow number carries {value, baseline, n_vessels, methodology,
confidence}".

Input schema:
- sourceType: operator | regulator | ais | satellite | press | classifier | derived
- method: short free-text ("AIS-DWT calibrated", "GIE AGSI+ daily")
- sampleSize + sampleLabel: observation count and unit
- updatedAt: ISO8601 / Date / number — rendered as "Xm/h/d ago"
- confidence: 0..1 — bucketed to high/medium/low
- classifierVersion: surfaced when evidence-derived badges ship in Week 2+
- creditName / creditUrl: CC-BY / dataset credit (OWID, GEM pattern)

Every field also writes data-attributes (data-attr-source, data-attr-n,
data-attr-confidence, data-attr-classifier) so MCP / scraper / analyst
agents can extract the same provenance the reader sees. Agent-native by
default.

Applied to ChokepointStripPanel — the panel now shows its evidence
footer ("AIS calibration · Portwatch DWT + AIS · N AIS disruption
signals · updated Xh ago · EIA World Oil Transit Chokepoints").
Future pipeline / storage / shortage panels drop the same helper in
and hit the same rigour bar automatically.

7 unit tests (tests/attribution-footer.test.mts, node:test via tsx):
minimal footer, method + sample size + credit, "X ago" formatting,
confidence band mapping, full data-attribute emission, credit omission,
HTML escaping.

## Day 5 — Public methodology page stubs (docs/methodology/)

Four new MDX pages surfaced in docs/docs.json navigation under
"Intelligence & Analysis":

- chokepoints.mdx — 7 chokepoints, Portwatch+AIS calibration method,
  status badge derivation, known limits, revision-log link.
- pipelines.mdx — curated critical-asset scope, GEM CC-BY attribution,
  evidence-schema (NOT conclusion labels), freshness SLA, corrections.
- storage.mdx — curated ~125 facilities scope, "published not
  synthesized" fill % policy, country-aggregate fallback, attribution.
- shortages.mdx — automated tiered evidence threshold, LLM second-pass
  gating, auto-decay cadence, evidence-source transparency, break-glass
  override policy (admin-only, off critical path).

All four explicitly document WorldMonitor's automated-data-quality
posture: no human review queues, quality via classifier rigour +
evidence transparency + auto-decay + public revision log.

Typecheck clean. attribution-footer.test.mts passes all 7 tests.
Addresses three High findings from PR review:

1. Map-layer isolation (src/config/map-layer-definitions.ts)
   - Add 'energy' to the MapVariant type union.
   - Add energy entry to VARIANT_LAYER_ORDER with the curated energy
     subset (pipelines, waterways, commodityPorts, commodityHubs, ais,
     tradeRoutes, minerals, sanctions, fires, climate, weather, outages,
     natural, resilienceScore, dayNight).
   Without this, getLayersForVariant() and sanitizeLayersForVariant()
   (called from DeckGLMap and App.ts) fell back to VARIANT_LAYER_ORDER.full,
   letting the full geopolitical palette (military, nuclear, iranAttacks,
   conflicts, hotspots, bases, protests, flights, ucdpEvents,
   displacement, gpsJamming, satellites, ciiChoropleth, cables,
   datacenters, economic, cyberThreats, spaceports, irradiators,
   radiationWatch) into the desktop map tray and saved/URL layer
   sanitization — breaking the PR's stated no-geopolitical-bleed goal
   and violating multi-variant-site-data-isolation.

2. News feeds (src/config/feeds.ts + src/app/data-loader.ts)
   - Add ENERGY_FEEDS with three keys matching ENERGY_PANELS: live-news
     (broad energy headlines from OilPrice, Rigzone, Reuters/Bloomberg/FT
     energy), energy (OPEC + crude + NatGas/LNG + pipelines/chokepoints
     + crisis/shortages + refineries), supply-chain (tanker/shipping,
     chokepoints, energy sanctions, ports/terminals).
   - Add SITE_VARIANT === 'energy' branch to the FEEDS variant selector.
   - Correct newsCategories override in data-loader.ts — my earlier
     speculative values ['energy','energy-markets','oil-gas-news',
     'pipeline-news','lng-news'] included keys that did not exist in
     any feed map. Replaced with real ENERGY_FEEDS keys ['live-news',
     'energy', 'supply-chain'].
   Without this, FEEDS resolved to FULL_FEEDS for the energy variant —
   live-news + daily-brief both ingested the world/geopolitical feed set.

3. Insights / AI brief framing (src/components/InsightsPanel.ts)
   - Add SITE_VARIANT === 'energy' branch to geoContext: dedicated energy
     prompt focused on physical supply (pipelines, chokepoints, storage,
     days-of-cover, refineries, LNG, sanctions, shortages) with
     evidence-grounded attribution, no bare conclusions.
   - Add '⚡ ENERGY BRIEF' heading branch in renderWorldBrief().
   Without this, the renamed 'AI Energy Insights' panel fell through
   to the empty default prompt and rendered 'WORLD BRIEF'.

Typecheck clean. attribution-footer tests still pass (no coupling changed).
Fifth High finding from PR review: src/components/Map.ts createLayerToggles()
(line 381-409) has no 'energy' branch in its variant ternary, so energy-variant
users whose MapContainer routes to the SVG/mobile fallback (no WebGL, mobile
with deviceMemory < 3, or DeckGL init throws) see the full geopolitical toggle
set — iranAttacks, conflicts, hotspots, bases, nuclear, irradiators, military,
protests, flights, gpsJamming, ciiChoropleth, cables, datacenters.

Clicking any toggle flips the layer via toggleLayer() which is variant-blind
(Map.ts:3383) — so users could enable military / nuclear layers on the energy
variant despite the rest of the isolation work in panels.ts,
map-layer-definitions.ts, feeds.ts, and InsightsPanel.ts.

Fix: add energyLayers array with the SVG-capable subset of ENERGY_MAP_LAYERS —
pipelines, waterways, ais, commodityHubs, minerals, sanctions, outages, natural,
weather, fires, economic. Intentionally omitted: commodityPorts, climate,
tradeRoutes, resilienceScore, dayNight — none of these have render handlers in
Map.ts's SVG path, so including them would create toggles that do nothing.
Extended the ternary with 'energy' → energyLayers between 'happy' and the
'full' fallback.

Note (preexisting, NOT fixed here): the same ternary has no 'commodity' branch
either, so commodity.worldmonitor.app also gets the full geopolitical toggle
set on the SVG fallback. Out of scope for this PR; flagged for a separate fix.

Defence-in-depth: sanitizeLayersForVariant() (now fixed in
map-layer-definitions.ts) strips saved-URL layers to the energy subset before
the SVG map sees them, so even if a user arrives with ?layers=military in the
URL, it's gone by the time initialState reaches MapComponent. The toggle-list
fix closes the UI-path leak; the sanitize fix closes the URL-path leak.

Typecheck clean.
@koala73
koala73 marked this pull request as ready for review April 22, 2026 13:44
@greptile-apps

greptile-apps Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR scaffolds the energy variant for energy.worldmonitor.app, wiring variant detection, panel/layer configs, a ChokepointStripPanel (7 chokepoints), an attribution footer utility, and an SVG/mobile map isolation fix. The isolation work is thorough — hostname routing, Tauri storage allowlist, sanitizeLayersForVariant, and the SVG fallback ternary all include the new variant.

  • P1: dover_strait is labeled 'Danish Straits' in ChokepointStripPanel; the Strait of Dover (English Channel) and the Danish Straits (Baltic entry passages) are distinct geographic chokepoints — this is a visible factual error in the atlas's headline feature.
  • P2: energy.ts (the "reference" file) already diverges from the runtime panels.ts wiring on its first PR ('renewable-energy' vs 'renewable', 'hormuz' vs 'hormuz-tracker'), weakening it as a canonical reference.

Confidence Score: 4/5

Safe to merge after fixing the Dover Strait label; the isolation scaffolding is solid.

One P1 finding — a wrong geographic name displayed to users in the atlas's top-priority chokepoint strip. All other findings are P2. The variant isolation work (layer sanitization, SVG fallback fix, hostname routing) is well-executed.

src/components/ChokepointStripPanel.ts (wrong chokepoint label), src/config/variants/energy.ts (stale panel IDs in reference file)

Important Files Changed

Filename Overview
src/components/ChokepointStripPanel.ts New panel rendering 7-chokepoint status strip; dover_strait is mislabeled 'Danish Straits' (should be 'Dover Strait').
src/config/variants/energy.ts Reference-only variant config file; already diverges from runtime panels.ts with wrong panel IDs ('renewable-energy' vs 'renewable', 'hormuz' vs 'hormuz-tracker').
src/config/panels.ts ENERGY_PANELS, ENERGY_MAP_LAYERS, and ENERGY_MOBILE_MAP_LAYERS added and wired into all variant-selector ternaries; chokepoint-strip panel registered; missing from PANEL_CATEGORY_MAP.
src/config/map-layer-definitions.ts Energy added to MapVariant union and VARIANT_LAYER_ORDER; sanitizeLayersForVariant closes URL-injection path for energy; layer ordering looks correct.
src/components/Map.ts energyLayers array added to SVG/mobile fallback ternary, closing the geopolitical layer UI-path leak for energy variant.
src/utils/attribution-footer.ts New reusable attribution footer utility with proper HTML escaping, data attributes, and confidence banding; well-tested.
tests/attribution-footer.test.mts Comprehensive tests covering minimal render, method/sample/credit, timestamp formatting, confidence bands, data-attributes, and XSS escaping.
src/config/variant-meta.ts Energy Atlas metadata (title, description, keywords, features) added with well-formed SEO content.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Browser / Tauri] -->|hostname or localStorage| B{SITE_VARIANT resolver\nvariant.ts}
    B -->|energy.*| C[SITE_VARIANT = 'energy']
    C --> D[panels.ts\nENERGY_PANELS\nENERGY_MAP_LAYERS]
    C --> E[map-layer-definitions.ts\nVARIANT_LAYER_ORDER.energy\nsanitizeLayersForVariant]
    C --> F[Map.ts createLayerToggles\nenergyLayers SVG fallback]
    D --> G[panel-layout.ts\nChokepointStripPanel\nInsightsPanel energy brief]
    E --> H[URL ?layers= sanitized\nto energy-allowed set]
    F --> I[SVG/mobile map\nno geopolitical toggles]
    G --> J[ChokepointStripPanel\nfetchChokepointStatus\nattributionFooterHtml]
Loading

Comments Outside Diff (1)

  1. src/config/panels.ts, line 1193-1299 (link)

    P2 chokepoint-strip absent from PANEL_CATEGORY_MAP

    The new chokepoint-strip panel is not listed under any category in PANEL_CATEGORY_MAP. Other energy-variant panels (oil-inventories, fuel-prices, energy-crisis, etc.) are similarly absent. Users browsing the energy variant's panel settings by category will not be able to filter to this panel. Adding an energyInfra category group (mirroring commodityPrices for the commodity variant) would make the settings UI coherent for the energy variant.

Reviews (1): Last reviewed commit: "fix(variant): close energy-variant leak ..." | Re-trigger Greptile

suez: 'Suez',
bab_el_mandeb: 'Bab el-Mandeb',
bosphorus: 'Turkish Straits',
dover_strait: 'Danish Straits',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Incorrect geographic label for dover_strait

dover_strait is mapped to 'Danish Straits', but the Strait of Dover (English Channel narrows between SE England and NE France) and the Danish Straits (Øresund/Great Belt/Little Belt connecting the North Sea to the Baltic) are entirely different geographic chokepoints. An Energy Atlas showing the wrong name for a strategic shipping chokepoint is a material data-quality issue.

Suggested change
dover_strait: 'Danish Straits',
dover_strait: 'Dover Strait',

Comment on lines +26 to +28
hormuz: { name: 'Strait of Hormuz Tracker', enabled: true, priority: 1 },
'energy-crisis': { name: 'Energy Crisis Policy Tracker', enabled: true, priority: 1 },
'renewable-energy': { name: 'Renewable Energy', enabled: true, priority: 2 },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Reference file already diverges from runtime panel IDs

energy.ts is documented as "modify both if the variant shape changes", but it already uses panel IDs that don't exist at runtime:

  • 'renewable-energy' (line 28) — runtime panels.ts ENERGY_PANELS registers 'renewable'
  • 'hormuz' (line 26) — runtime panels.ts ENERGY_PANELS registers 'hormuz-tracker'

Since this file is never imported, there's no compile-time guard to catch drift. A developer following this file as the canonical reference would create or wire panels with the wrong keys, causing silent no-ops. Consider either aligning the IDs here with panels.ts or adding a CI script that asserts key parity between the two files.

@koala73
koala73 merged commit a17a338 into main Apr 22, 2026
10 checks passed
@koala73
koala73 deleted the feat/energy-atlas-release-1 branch April 22, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant