feat/atlas-scan
needs attentionviewing older commitcb8d915 · incrementalpre-PRreviewed 2026-08-12 17:29 UTC2H · 5M · 3L · 2I- Purpose
- Branch captures Atlas market intelligence tooling: a private atlas route behind platform login and a CFE distribution-grid scraping pipeline (WFS + per-circuit hosting capacity) to validate whether Power Finder transmission signals correlate with distribution-layer capacity constraints.
- Goal
- Determine if CFE distribution grid data corroborates the Power Finder's red-zone signal, enabling or reframing the enterprise solar GD product positioning.
- Sub-goals
- SG-1: Authenticated /atlas route with platform login guard
- SG-2: CFE GeoServer WFS pipeline — circuit enumeration, transformer georeferencing, hosting capacity per circuit
- SG-3: Pilot on Los Mochis corridor (green PF zone) — 6/6 circuit agreement
- SG-4: Division-wide runner — survives CFE blocks, resumable via SQLite
- SG-5: Falsifiable test — capture PF-red zones (Monterrey, Guadalajara) as negative cases
- What
- Added test_falsable.py: a standalone orchestrator that (a) polls CFE availability, (b) tiles a PF-red city bbox to enumerate circuits + division codes into SQLite, (c) triggers dist_trafos and dist_capacity per discovered division, producing the dataset for dist_compare.py to compare against the green Los Mochis baseline.
- Why
- The Los Mochis pilot had a degenerate test — all substations were green and all circuits had slack, so the '6/6 agreement' would have been identical with random data. The negative cases (PF-red zones) are required to make the falsification real.
- Areas
- scripts/atlas/distribucion+13680−1apps/platform+345−1apps/web + apps/{web+852−57scripts/atlas/pland+0−0
- Blast
- 126 files, +14,879/−59 total; 86 files in scripts/atlas (research spike — no production impact); 15 files in apps/platform (atlas route, tracing); 1 file in apps/web.
Findings · 11
correctness4
seg_count never accumulated on upsert — always stays at 1
scripts/atlas/distribucion/test_falsable.py:59
The ON CONFLICT clause updates `division_code` but not `seg_count`; the INSERT hardcodes `1`. dist_enumerate.py correctly accumulates with `seg_count = circuit.seg_count + excluded.seg_count`. Circuits spanning multiple tiles (common at 0.1° step over a 0.5°×0.35° bbox like Monterrey) will always show seg_count=1, making any downstream query that uses seg_count as a circuit-size proxy unreliable.
libre() probes a different WFS layer and bbox — can give false 'disponible'
scripts/atlas/distribucion/test_falsable.py:26
libre() queries `sigdis:subestacion` in the Los Mochis bbox ([-109.0, 25.7, -108.9, 25.8]) to check reachability, but the main loop fetches `sigdis:linea_mta_hc` in the Monterrey/Guadalajara bbox. CFE may allow the subestacion layer while blocking linea_mta_hc, so the liveness check returns True and the script proceeds, only to break on the first tile with a 403 having done zero useful work. The probe should query the same layer (or at least the same bbox) the main loop uses.
None division codes silently excluded from analysis after being inserted
scripts/atlas/distribucion/test_falsable.py:55
`p.get('division')` returns None when the property is absent; None is added to `divisiones` and inserted into the DB as `division_code=NULL`. The downstream loop guards `if not dv: continue`, silently excluding those circuits from transformer and capacity analysis. Filter at collection time (`if cc and p.get('division')`) to make the exclusion explicit and avoid polluting the DB with null rows.
Float tile accumulation drift — loop counter not rounded
scripts/atlas/distribucion/test_falsable.py:31
`x += step` and `y += step` accumulate floating-point error; the round() on yielded values doesn't affect the loop counter. For Monterrey's ~25 tiles this is negligible, but using `x = bbox[0] + n * step` with integer `n` is the conventional fix. Consider for larger bboxes.
security1
SSL verification disabled (inherited from dist_common) — data integrity not guaranteed
scripts/atlas/distribucion/test_falsable.py:1
All WFS calls go through dist_common's CERT_NONE context. Data from CFE GeoServer cannot be integrity-verified. Accepted and documented in dist_common.py as a workaround for CFE's cert chain; no action needed unless auth is ever added to the endpoint.
conventions2
CLI arg parsing is fragile — IndexError and KeyError on invalid input
scripts/atlas/distribucion/test_falsable.py:91
`sys.argv[sys.argv.index('--zona') + 1]` raises IndexError if --zona is the last token; `main(zk)` raises KeyError if the zone key is unknown. One guard: `if zk not in ZONAS: sys.exit(f'zona desconocida: {zk!r} — válidas: {list(ZONAS)}')` prevents both cryptic failures without adding any dependency.
DB connection never explicitly closed on early exit
scripts/atlas/distribucion/test_falsable.py:47
`con = C.db()` is never wrapped in `with` or closed in a finally block. On a 403 break the process exits and SQLite's WAL recovers, but an explicit `con.close()` in a finally block is cleaner and avoids file-lock issues if the caller ever reuses the process.
tests1
No pre-committed numeric threshold for 'apretado' — outcome is ambiguous
scripts/atlas/distribucion/test_falsable.py:1
The docstring anchors the green baseline at 4.1% (Los Mochis) but never states what utilisation level counts as 'notoriamente más apretado'. Without a pre-committed threshold, any observed value above 4.1% can be argued either way post-hoc. For a true falsifiable test, define the decision boundary before running (e.g. '>15% median utilisation = corroborated').
improvement3
tiles() is duplicated from dist_enumerate.py
scripts/atlas/distribucion/test_falsable.py:27
An identical tiles() generator exists in dist_enumerate.py. The only difference is the default step (0.1 here vs 0.12 elsewhere — 44% more WFS calls). Consider importing from dist_enumerate or moving to dist_common.py. If 0.1 is intentional for urban density, add a constant (STEP = 0.1) with a comment.
libre() is duplicated from division_run.py
scripts/atlas/distribucion/test_falsable.py:19
The same probe pattern appears in division_run.py (libre()) and pilot_run.py (disponible()). A shared C.probe_libre() in dist_common.py would eliminate three copies. For a research spike, even a direct `from division_run import libre` would reduce drift.
step=0.1 vs 0.12 in sibling scripts — silent WFS load increase
scripts/atlas/distribucion/test_falsable.py:27
Other scripts use step=0.12; this uses 0.1, producing ~44% more tiles. For urban bboxes (Monterrey: ~25 vs 18 tiles) the difference is small but a comment or named constant (STEP = 0.1) would signal this is deliberate.
History · 16 commits
- 91aaedfsafeincremental0H · 1M · 1L2026-08-12 17:35
- cb8d915needs attentionincremental2H · 5M · 3L2026-08-12 17:29current
- 4cbbe8aneeds attentionincremental0H · 3M · 8L2026-08-12 14:01
- 4aa3c02needs attentionincremental2H · 3M · 3L2026-08-12 02:35
- f5630b2needs attentionincremental0H · 4M · 5L2026-08-12 02:17
- 28fde5bneeds attentionincremental1H · 2M · 2L2026-08-12 01:53
- 0babe51needs attentionincremental1H · 2M · 5L2026-08-12 01:23
- 50e8a8cneeds attentionincremental3H · 5M · 7L2026-08-11 23:58
- 3af4686needs attentionincremental3H · 5M · 5L2026-08-03 20:07
- f5d3266needs attentionincremental0H · 3M · 8L2026-08-03 19:40
- 9f8b61aneeds attentionincremental0H · 2M · 3L2026-08-03 19:15
- ea51fa0needs attentionincremental1H · 4M · 4L2026-08-03 19:02
- 2b33f2fneeds attentionincremental0H · 1M · 1L2026-07-18 05:09
- 2f8cf79needs attentionincremental1H · 3M · 4L2026-07-18 00:59
- 1616332safeincremental0H · 0M · 1L2026-07-18 00:22
- e997fd8needs attentionfull1H · 4M · 6L2026-07-17 23:53