claude/vigorous-stonebraker-41cc2d
needs attentionviewing older commit64dc83d · incrementalpre-PRreviewed 2026-07-13 20:03 UTC0H · 1M · 7L · 1I- Purpose
- Interactive public energy map of Mexico's SEN grid — showcasing CFE generation, transmission, tarifas, and planned projects
- Goal
- Add a 'private generation' layer: 18 privately-approved solar/wind projects from CNE's 1ª Convocatoria de Atención Prioritaria (planeación vinculante, Dec 2025)
- Sub-goals
- SG-1: New data file private_generation.json with 18 projects (CNE/SENER source)
- SG-2: Wire fetch → GeoJSON FeatureCollection → map source/layer
- SG-3: Click popup with project name, MW, storage, COD year, developer, location, MIA, source attribution
- SG-4: Layer toggle button ('Generación privada (planeación vinculante)', #c084fc, off by default)
- SG-5: Coordinate precision encoded in circle opacity (exact=0.6, near/muni=0.35)
- What
- New file apps/web/public/atlas/data/private_generation.json (18 projects). apps/web/public/atlas/index.html: adds 7th Promise.all fetch, builds privFC FeatureCollection, adds privgen source/layer, click handler, GROUPS/TOGS entry.
- Why
- Completes the branch's full planned-capacity picture alongside CFE's own construction/planning layer and Plan SEN transmission — giving users visibility into both public and private capacity additions.
- Areas
- apps/web/public/atlas/data/private_generation.json+24−0apps/web/public/atlas/index.html+7−4
- Blast
- 2 files, +31/-4. Entire change is within the standalone atlas app (apps/web/public/atlas/). No backend, no API, no database, no other app affected. Static asset change only.
Findings · 9
correctness2
Three Singuilucan projects render as overlapping circles — two may be unclickable
apps/web/public/atlas/data/private_generation.json:9
Saturno Solar (19.9713, -98.5750), Akuwa Solar (19.9660, -98.5680), and Delfín Solar (19.95, -98.56) are co-located in Singuilucan, Hidalgo. At default zoom levels the lower-z-order circles are occluded, making them unclickable. No clustering or jitter logic is present in the layer. Acceptable given 'muni' precision for Delfín, but worth noting.
mia field mixes MIA expedient codes with free-text status notes
apps/web/public/atlas/data/private_generation.json:17
Most entries use structured SEMARNAT codes (e.g. '13HI2025E0096'). Three entries use prose: 'aprobada 2026', 'aprobada', 'MIA-R 2025'; one uses a project name 'P.E. Panabá 1A/1B'. These render literally as 'MIA aprobada 2026' in the popup. If the field is ever used for registry lookup or URL-linking these will fail. Use '' for unknown codes and keep mia as a code-only field.
security1
Unsanitized field interpolation in popup HTML template
apps/web/public/atlas/index.html:304
Popup is built via template literals: `<b>${p.n}</b>`, `${p.dev}`, `${p.mia}`, etc., passed to a pop() function that likely sets innerHTML. Risk is low because the data source is a static, checked-in JSON file — not user input. However, if the JSON file is ever compromised or the source changes to a dynamic API, all string fields become an XSS vector. Mitigation: add a small escapeHtml(s) = s.replace(/&/g,'&').replace(/</g,'<') and wrap all interpolated fields.
conventions3
About panel 'Fuentes de datos' missing CNE/SENER and Plan SEN entries
apps/web/public/atlas/index.html:136
The about panel lists 6 data sources but omits CNE/SENER (private_generation.json: '1ª Convocatoria de Atención Prioritaria') and CFE/Plan SEN (transmission.json added in the prior commit). The established convention is every dataset visible on the map has a corresponding 'Fuentes de datos' entry. Add: '<b>CNE · SENER</b> — proyectos aprobados (planeación vinculante, 1ª Convocatoria); <b>CFE · Plan SEN 2025-2030</b> — transmisión planeada'.
dev: 'n/d' sentinel bypasses empty-string fallback — renders literally in popup
apps/web/public/atlas/data/private_generation.json:22
The privFC mapping uses p.dev||'' and the popup uses p.dev?'<br>'+p.dev:''. The 'n/d' string is truthy, so it renders as a developer line reading 'n/d' rather than omitting the line. The consistent sentinel for 'unknown developer' in this codebase is '' (empty string).
GROUPS key order does not match TOGS render order
apps/web/public/atlas/index.html:307
GROUPS defines keys as {..., tx, privgen} (tx before privgen) but TOGS renders them as [..., privgen, tx]. The prior convention was to keep GROUPS and TOGS in the same logical order for readability. Move 'privgen:['privgen']' before 'tx:[...]' in GROUPS to match.
tests1
No data-integrity validation for atlas JSON files
apps/web/public/atlas/data/private_generation.json
The atlas has no test suite (standalone HTML, intentional). A lightweight Node/Vitest data integrity script checking required fields, valid lat/lng ranges, and numeric capacity would be the highest-leverage first test to add — catching entry errors like invalid mia codes or out-of-Mexico coordinates at CI time.
improvement2
Silent fetch failure — no console.warn when private_generation.json fails to load
apps/web/public/atlas/index.html:244
The .catch(()=>({projects:[]})) swallows all fetch errors. A 404 (e.g. during a deploy gap) would render the toggle button functional but the layer empty with no diagnostic. Add console.warn('privgen fetch failed', err) in the catch to aid debugging.
Projects with cod=0 show no COD indicator — consider 'año desconocido' label
apps/web/public/atlas/index.html:304
Three projects (Central Eólica 24, Global Hidalgo 2, Vientos del Caribe) have cod:0 (unknown). The popup renders `p.cod?' · op. '+p.cod:''` — so cod=0 shows nothing (0 is falsy — correct, no spurious '0'). However, users have no way to know COD is unknown vs simply not shown. Consider 'op. año desconocido' fallback for these three.
History · 10 commits
- a081002safeincremental0H · 0M · 0L2026-07-14 01:23
- 64dc83dneeds attentionincremental0H · 1M · 7L2026-07-13 20:03current
- ec4eea3needs attentionincremental1H · 3M · 7L2026-07-13 18:42
- f4b4129safeincremental0H · 0M · 3L2026-07-13 04:34
- 8ea0c8asafeincremental0H · 0M · 3L2026-07-13 04:21
- 37ce28asafeincremental0H · 2M · 3L2026-07-10 17:22
- d28c6daneeds attentionincremental0H · 3M · 10L2026-07-10 16:59
- 754a65dneeds attentionincremental0H · 3M · 4L2026-07-10 16:39
- a9190b2safeincremental0H · 0M · 5L2026-07-10 16:14
- 0bf12a0blockedfull1H · 2M · 4L2026-07-10 16:06