mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
* feat(energy-atlas): promote Atlas map layers to FULL variant (§R #3 = B)
Per plan §R/#3 decision B: the Redis-backed evidence registries
(75 gas + 75 oil pipelines, 200 storage facilities, 29 fuel shortages)
are now toggleable on the main worldmonitor.app map. Previously they
were hardcoded energy-variant-only, and FULL users who toggled
`pipelines: true` got the ~20-entry legacy static PIPELINES list.
Changes:
- `src/components/DeckGLMap.ts`: drop the `SITE_VARIANT === 'energy'`
gates at :1511-1541. The pipelines layer now always uses
`createEnergyPipelinesLayer()` (Redis-backed evidence registry);
`createPipelinesLayer` (legacy static) is left in the file as dead
code pending a separate cleanup PR that also retires
`src/config/pipelines.ts`. Storage and fuel-shortage layers are
now gated only on the variant's `mapLayers.storageFacilities` /
`mapLayers.fuelShortages` booleans.
- `src/config/panels.ts`: add `storageFacilities: false` +
`fuelShortages: false` to FULL_MAP_LAYERS (desktop + mobile) so
the keys exist for toggle dispatch; default off so users opt in.
- `src/config/map-layer-definitions.ts`: extend the `full` variant's
VARIANT_LAYER_ORDER to include `storageFacilities` and
`fuelShortages`, so `getAllowedLayerKeys('full')` admits them and
the layer picker surfaces them.
- `src/config/commands.ts`: add CMD+K toggles
`layer:storageFacilities` and `layer:fuelShortages` next to the
existing `layer:pipelines`.
Finance + commodity variants already had `pipelines: true`; they
now render the more comprehensive Redis-backed 150-entry dataset
instead of the ~20-entry legacy list. If a variant doesn't want
this, they set `pipelines: false` in their MAP_LAYERS config.
Part of docs/internal/energy-atlas-registry-expansion.md §R.
* fix(energy-atlas): restrict storageFacilities + fuelShortages to flat renderer
Reviewer (Codex) found two gaps in PR #3366:
1. GlobeMap 3D toggles did nothing. LAYER_REGISTRY declared both new
layers with the default ['flat', 'globe'] renderers, so the toggle
showed up in globe mode. But GlobeMap.ts has no rendering support:
ensureStaticDataForLayer (:2160) only handles cables/pipelines/etc.,
and the layer-channel map (:2484) has no entries for either. Users
in globe mode saw the toggle and got silent no-ops.
2. SVG/mobile fallback (Map.ts fullLayers at :381) also has no render
path for these data types. The existing cyberThreats precedent at
:387 documents this as an intentional DeckGL-only pattern.
Fix:
- Restrict both LAYER_REGISTRY entries to ['flat'] explicitly. The
layer picker hides the toggle in globe mode instead of exposing a
no-op. Comment points to the GlobeMap gap so a future globe-rendering
PR knows what to undo.
- Extend the existing cyberThreats note in Map.ts:387 to cover
storageFacilities + fuelShortages too, noting they're already
hidden from globe mode via the LAYER_REGISTRY restriction.
This is the smallest possible fix consistent with the pre-existing
pattern. Full globe-mode rendering for these layers is out of scope —
tracked separately as a follow-up.
* fix(energy-atlas): gate layer:* CMD+K by current renderer + DeckGL state
Reviewer follow-up on PR #3366: the previous fix restricted
LAYER_REGISTRY renderers to ['flat'] so the globe-mode layer picker
hides storageFacilities / fuelShortages toggles. But CMD+K was still
callable — SearchModal.matchCommands didn't filter `layer:*` commands
by renderer, so a user could CMD+K "storage layer" in globe or SVG
mode and trigger a silent no-op.
Fix — centralize "can this layer render right now?" in one helper:
- Add `deckGLOnly?: boolean` to LayerDefinition. `renderers: ['flat']`
is not enough because `'flat'` covers both DeckGL-flat and SVG-flat,
and the SVG/mobile fallback has no render path for either layer.
Mark both as `deckGLOnly: true`.
- New `isLayerExecutable(key, renderer, isDeckGLActive)` helper in
map-layer-definitions.ts. Returns true iff renderers include the
current renderer AND (if deckGLOnly) DeckGL is active.
- `SearchModal.setLayerExecutableFn(fn)`: caller-supplied predicate
used in both `matchCommands` (search results) and
`renderAllCommandsList` (full picker).
- `search-manager` wires the predicate using `ctx.map.isGlobeMode()`
+ `ctx.map.isDeckGLActive()`, and also adds a symmetric guard in
the `layer:` dispatch case so direct activations (keyboard
accelerator, programmatic invocation) bail the same way.
Pre-existing resilienceScore DeckGL gate at search-manager:494 kept as
a belt-and-suspenders — the new isLayerExecutable check already
covers it since resilienceScore has `renderers: ['flat']` (though it
lacks deckGLOnly). Left the specific check in place to avoid scope
creep on a working guard.
Typecheck clean, 6694/6694 tests pass.
* fix(energy-atlas): filter CMD+K layer commands by variant too
Greptile P2 on commit 3f7a40036: `layer:storageFacilities` and
`layer:fuelShortages` still surface in CMD+K on tech / finance /
commodity / happy variants (where they're not in VARIANT_LAYER_ORDER).
Renderer + DeckGL filter was passing because those variants run flat
DeckGL. Dispatch silently failed at the `variantAllowed` guard in
handleCommand (:491), producing an invisible no-op from the user's
POV.
Fix: extend `setLayerExecutableFn` predicate to also check
`getAllowedLayerKeys(SITE_VARIANT).has(key)` before the renderer
checks. SearchModal now hides these commands on non-full/non-energy
variants where they can't execute.
This also cleans up the pre-existing pattern for other
variant-specific layer commands flagged by Greptile as "consistent
with how other variant-specific layer commands (e.g. layer:nuclear
on tech variant) already behave today" — they now all route through
the same predicate.
* fix(energy-atlas): gate layers:* presets + add isLayerExecutable tests (review P2)
Two Codex P2 findings on this PR:
1. `layers:*` presets bypassed the renderer/DeckGL gate.
`search-manager.ts:481` checked only `allowed.has(layer)` before
flipping a preset layer on. A user in globe mode or on SVG
fallback who ran `layers:all` or `layers:infra` would silently
set `deckGLOnly` layers (storageFacilities, fuelShortages) to
true — toggles with no rendered output, and since the picker
hides those layers under the current renderer the user had no
way to toggle them back off without switching modes.
Fix: funnel presets through the same `isLayerExecutable`
predicate per-layer CMD+K already uses. `executable(k)` combines
the existing `allowed.has` variant check with the renderer + DeckGL
gate, so presets now match the per-layer dispatch behavior exactly.
2. No regression tests for the `deckGLOnly` / `isLayerExecutable`
contract, despite it being behavior-critical renderer gating.
Fix: added `tests/map-layer-executable.test.mts` — 16 cases:
- Flag assertions: storageFacilities + fuelShortages carry
`deckGLOnly: true` and renderers: ['flat']. Layers without the
flag (pipelines, conflicts, cables) have it `undefined`, not
accidentally `false`.
- Renderer-gate cases: deckGLOnly layers pass only on flat + DeckGL
active, not on SVG fallback, not on globe. Flat-only non-deckGLOnly
layers (ciiChoropleth) pass on flat regardless of DeckGL status.
Dual-renderer layers (pipelines) pass on both flat and globe.
Unknown layer keys return false.
- Exhaustive 2×2×2 matrix across (renderer, isDeckGL, deckGLOnly)
using representative layer keys for each shape.
All 16 new tests pass. Full test:data suite still green. Typecheck clean.
* fix(energy-atlas): add pipeline-status to finance + commodity panel sets (review P1)
Codex P1: FINANCE_MAP_LAYERS and COMMODITY_MAP_LAYERS both carry
`pipelines: true`, and PR #3366 unified all variants on
`createEnergyPipelinesLayer` which dispatches
`energy:open-pipeline-detail` on row click. The listener for that
event lives in PipelineStatusPanel.
`PanelLayoutManager.createPanel()` only instantiates panels whose keys
are present in `panelSettings`, which derives from FULL_PANELS /
FINANCE_PANELS / etc. — so on finance and commodity variants the
listener never existed, and pipeline clicks were a silent no-op.
Fix: add `pipeline-status` to both FINANCE_PANELS and COMMODITY_PANELS
with `enabled: false` (panel slot not auto-opened; users invoke it by
clicking a pipeline on the map or via CMD+K). The panel now
instantiates on both variants and the click-through works end to end.
FULL_PANELS + ENERGY_PANELS already had the key from earlier PRs;
no change there.
Typecheck clean, test:data 6696/6696 pass.