Domain A - China Industrial Activity vs. Satellite Reality

H1: National divergence index (z(official) - z(composite satellite))3.471.980.50-0.99-2.47+2sigma2024-06-012025-06-012026-05-01sigma units
Source: China NBS (industrial output) vs. NASA Black Marble night lights + Sentinel-5P NO2 + IMF PortWatch export volume, via FactIQ   Period: 2024-06 to 2026-05 (20 months)   Harvest date: 2026-08-04
⚠ FactIQ's official NBS data is not vintage-aware (Phase 1) - every value is today's revised print, not the original.

Domain A — Results: China Industrial Activity vs. Satellite Reality

Computed 2026-08-04 against hypothesis.md (commits d918279, 118e5a7, pre-registered before any value was fetched). Every number below is reproducible: python -m src.domains.domain_a_china.compute regenerates results.json from the staged fixtures in data/, deterministically, with no manual or LLM arithmetic in the computation path.

H1 — National divergence index: weak positive, technically not falsified

H2 — Yunnan dry-season signal: dip present, not falsified, and distinct from a national pattern

Antithesis checks performed

Data-quality finding surfaced during staging (not anticipated in the hypothesis)

Both nighttime-lights series' catalog metadata claimed begin_time: 2024-01-01. The underlying data_points table actually has complete monthly coverage back to 2019-01-01 (89 of 89 possible months, no gaps) — confirmed via COUNT(*)/MIN/MAX against the raw table, not the series catalog. This is a sharper version of the Phase 0 finding that dataset-level metadata can be stale ("trust series.end_time, not dataset metadata") — here it extends to series-level begin_time being simply wrong. Practical effect: this project actually had ~5 more years of usable night-lights history available than the pre-registered hypothesis assumed, which is why H2's seasonal-index test could use 7 dry seasons' worth of data instead of the 2 originally anticipated. Anyone building further on FactIQ's satellite_nightlights catalog metadata should query data_points directly rather than trust begin_time/end_time on the series row.

Caveats (restated from hypothesis.md; all still apply)

Bottom line

Pre-registered hypothesis

Domain A — China Industrial Activity vs. Satellite Reality

Status: PRE-REGISTERED, 2026-08-04. No comparison values have been pulled at the time this file is committed — series existence and coverage windows only (metadata, not results). Per project principle, this hypothesis will not be edited after results are computed; if it fails, the failure is recorded, not the hypothesis.

Data sources (exact identifiers confirmed present as of 2026-08-04)

Official (FactIQ china schema, dataset nbs, National Bureau of Statistics of China):

Satellite/observed (FactIQ satellite schema, dataset satellite_nightlights, NASA Black Marble):

Air quality (FactIQ satellite schema, get_geo_data, live Sentinel-5P aggregation, no series_id — fetched by region/date range):

Shipping (FactIQ portwatch schema, dataset portwatch_countries):

H1 — National divergence index

Official monthly industrial value-added YoY growth and a satellite-derived composite industrial-activity YoY growth (built from national night lights, national NO2, and national port export volume) should be positively correlated over the overlap window — 2024-06 through 2026-05, ~24 monthly observations, bounded by the satellite series' 2024-01 start plus the 12-month YoY lag it requires.

Method (deterministic — implemented in compute.py, no manual or LLM judgment at compute time):

  1. For each of the three satellite/observed inputs, compute month-over- same-month-prior-year % change.
  2. Z-score each input's own YoY-change series, using that series' own mean/stdev over the overlap window (z-score against own history — the same convention already used project-wide for the drift check and the planned scout agent).
  3. Composite satellite signal = simple average of the three z-scores per month. Equal weighting, declared here in advance, not tuned after seeing results.
  4. Z-score the official industrial value-added YoY series the same way, over the same window.
  5. Divergence index = z(official) − z(composite satellite), by month.

Falsification: if the correlation between z(official) and the composite satellite z-score is ≤ 0 over the full window — no positive relationship at all — H1 is falsified. The "official vs. observed" comparison this domain is built on does not hold even directionally, and that will be reported as a failure, not adjusted.

H2 — Yunnan dry-season hydropower curtailment signal (aluminium overlay)

Method note (amended 2026-08-04, before any data was fetched — see note at end of section): uses a deseasonalized radiance ratio, not YoY growth.

The specific hydropower reservoirs needed to observe curtailment directly are confirmed absent from FactIQ (Phase 0 finding). This tests the necessarily weaker, indirect prediction instead: Yunnan's nighttime radiance should sit measurably below its own trailing 12-month baseline during the dry season (defined a priori as November–April, the conventional Yunnan hydropower low-water period) compared to non-dry-season months. If the curtailment story holds, national non-ferrous-metals-smelting value-added YoY growth should also tend to be relatively weaker in dry-season months — though this leg is expected to be weak and noisy, since the national series blends Yunnan with every other province and every other non-ferrous metal. That expectation is stated here, in advance, not fitted after the fact.

Method (deterministic, in compute.py):

  1. For each month of Yunnan radiance, compute a seasonal index = that month's radiance ÷ the trailing 12-month mean radiance ending that month (falls back to the longest available trailing window at the start of the series, logged explicitly, never silently padded).
  2. Classify each month as dry-season (Nov–Apr) or wet-season (May–Oct).
  3. Compare the mean seasonal index across dry-season months to the mean across wet-season months, over however many months of each are available in the window.

Why not YoY growth, as H1 uses: a YoY change in radiance compares a month to the same month one year earlier. If Yunnan curtails hydropower in the same months every year, both the numerator and its year-ago denominator are equally suppressed, and YoY growth would show no dip at all even if a real, stable seasonal pattern exists — YoY only reveals changes in curtailment severity between years, not the existence of the seasonal pattern itself. The deseasonalized ratio above is the direct test for a recurring dip; it is used here instead, and only here — H1 keeps its YoY-based method because H1 is explicitly comparing against an official series that is itself already YoY.

Falsification: if Yunnan's dry-season seasonal index is not measurably lower, on average, than its wet-season seasonal index, across the two dry seasons available in the window (Nov 2024–Apr 2025, and Nov 2025–Apr 2026 partial, bounded by data through 2026-05), H2's core physical claim is not supported by this data and will be reported as such. There is no reservoir data to fall back on — this is the whole test.

Amendment note: the original committed version of this section (commit d918279) specified a YoY-growth-based test for H2, which — on review before any data was touched — does not actually test for a recurring seasonal pattern, for the reason given above. This correction is made before any comparison value has been fetched (only series metadata had been queried at that point); it is a methodological fix caught in review, not a post-results adjustment, and is being committed as a visible amendment rather than silently folded into the original text.

Antithesis — required counter-checks before any result is called a finding

Caveats (known before results; will be restated in the results writeup)

Ask about the data covers every domain on the site

Password required.