diff --git a/AGENTS.md b/AGENTS.md index 28c1dae..296ca7f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,6 +37,7 @@ cd simulations/gadm02 && python3 -B predictions_v1.py # band ranges for the pr cd simulations/gadm02 && python3 -B calibrate_data.py && python3 -B calibrated_readings.py # calibration to measured data (models/Calibration.md) cd simulations/gadm02 && for j in US EU; do python3 -B gsa.py --model gadm04 --jobs 8 --start $j; done # GSA around calibrated starts, ~30 min cd simulations/gadm02 && python3 -B cross_border.py # coupled world US/EU/AR from the calibrated start (models/CrossBorder.md) +cd simulations/gadm02 && python3 -B world_scenarios.py # contexts X1–X4, hypothesis re-test, local vs. global ``` Reality checkpoints (ASSEMBLY-WP-0010): scheduled by activity-core and diff --git a/models/Calibration.md b/models/Calibration.md index d4f6dfc..4b42314 100644 --- a/models/Calibration.md +++ b/models/Calibration.md @@ -1,7 +1,9 @@ # Calibration of GADM-0.4 to measured data -**Status:** v0.4 (2026-10-13). ASSEMBLY-WP-0013, then the 2026-10-13 review -(§ 3.1): 35 of 39 targets measured, all 39 inside their ranges after fitting. Calibrates starting states +**Status:** v0.5 (2026-10-13). ASSEMBLY-WP-0013, then the 2026-10-13 review +(§ 3.1): 36 of 40 targets measured, all 40 inside their ranges after fitting. +v0.5 adds Argentina's ecological headroom (global planetary-boundary measure), +which fits AR's `ereg` (0.0058) instead of the default. Calibrates starting states for US, EU, DE and AR. Argentina has no measured adoption growth, so it is calibrated only on priors. Most state targets are literature priors that the next review must verify against checkpoint data. @@ -100,7 +102,7 @@ Fitted parameters per jurisdiction: | US | 2.00 | 1.2 y | 0.478 | 0.0062 | 0.387 | **0.26** (fitted to the B trend) | | EU | 1.54 | 0.9 y | 0.523 | 0.0063 | 0.719 | 0.60 (default) | | DE | 1.41 | 1.5 y | 0.616 | 0.0066 | 0.702 | 0.60 | -| AR | 2.00 | 1.1 y | 0.387 | 0.0500 | 0.580 | 0.60 | +| AR | 2.00 | 1.1 y | 0.387 | 0.0058 | 0.580 | 0.60 | **Fit: 39 of 39 targets inside their range, including 35 of 35 measured targets.** diff --git a/models/CrossBorder.md b/models/CrossBorder.md index 049fc1b..c958f41 100644 --- a/models/CrossBorder.md +++ b/models/CrossBorder.md @@ -169,3 +169,68 @@ concentration**, and the data allow at most a ≈ 0.006 per year. That is about Caveats: the foreign shares and κ are first estimates. The access rule is a removal rate on the operator part, not a model of how regulation works. The legitimacy loop is off. + +## 5. Context scenarios and hypothesis re-test (T04, T05) + +`world.py` supports **local runs in a context**: `context(rows)` makes a +jurisdiction follow given rows instead of being simulated (test: a local run +against a context taken from a global run reproduces that run to nine +decimals). `world_scenarios.py` (`results/world_scenarios.md`) runs four +contexts globally (US, EU, AR and a J4 reference bloc) with the legitimacy +loop off and on. Calibration v0.5 (Argentina's E measured too, 40 of 40 +targets in range). + +| Context | Definition | +|---|---| +| X1 US-led concentrated frontier | current levers | +| X2 open-lineage world | US moves to rights-first (J1) levers | +| X3 accelerating frontier | US and J4 with self-enhancement (B4-like) | +| X4 fragmented blocs | hosts' frontier access 0.2, foreign shares halved | + +Output is compared **relative to each jurisdiction's own start**. Model +output levels are normalized and not comparable across jurisdictions. + +### 5.1 "Europe lags" (H1) + +| | loop off | loop on | +|---|---|---| +| EU adoption below US and AR at t 10 | yes, in all four contexts | no, in all four contexts | +| EU − US relative output, years 0–25 | −0.03 to −0.24 (largest when the frontier accelerates) | −0.04 to +0.08 | +| EU − US VFAC at t 100 | +0.03 to +0.05, except open-lineage world −0.02 | +0.01 to +0.02, except open-lineage world −0.02 | + +Reading: Europe lags in adoption **only if sentiment does not matter**. With +the measured sentiment levels (US Σ 0.29, EU 0.54) and the legitimacy loop, +US adoption brakes and the EU no longer lags. Lagging costs output early, +most in an accelerating-frontier world, but the EU ends with higher VFAC than +the US unless the US itself moves to rights-first levers. + +### 5.2 "Argentina may thrive" (H2) + +Not supported in any context or loop setting. Relative to its start, +Argentina grows less than the EU (−0.02 to −0.07 over years 0–25) and ends +with lower VFAC (−0.04 to −0.06). It starts with the highest domination +(0.75), all of it run from abroad (f = 1), under deregulated levers. That +leaves no domestic lever on domination, and its frontier access does not +compensate. Argentina gains most from the open-lineage world (X2), that is, +from US policy, not from its own. + +### 5.3 When the context approximation fails + +For host outcomes, the local run in a context equals the global run (max |ΔP| +< 0.001), including with a strong EU access rule and spillover. Hosts do not +feed back on the home in the current coupling: spillover changes the +*home's* path, and the host already applies its own rule. Global runs are +therefore needed for the home's outcomes, for spillover effects on third +jurisdictions, and for frontier leadership changes. Local runs suffice for a +single host's questions. + +### 5.4 Limitations + +- Foreign shares f are fixed. In reality they would move with access rules + and domestic alternatives. +- Frontier access κ = 0.8 is a prior. +- The J4 bloc is uncalibrated. It reuses the US start with J4 levers. +- Trade, talent and sentiment contagion (C6–C8) are not modeled. +- No host rule reaches imported lineages (BR-008). + +These are handed to ASSEMBLY-WP-0016. diff --git a/simulations/gadm02/calibration_targets.json b/simulations/gadm02/calibration_targets.json index 454be37..310c8db 100644 --- a/simulations/gadm02/calibration_targets.json +++ b/simulations/gadm02/calibration_targets.json @@ -218,6 +218,12 @@ "hi": 1.65, "basis": "prior", "op": "no AR series yet; assumed within the US/EU/DE observed range (1.31-1.48)" + }, + "E": { + "lo": 0.15, + "hi": 0.32, + "basis": "measured", + "op": "Planetary Health Check 2025 (Stockholm Resilience Centre / PIK): 7 of 9 boundaries breached; E = share still in the safe zone = 2/9 = 0.22 (global) (checkpoints/2026/2026-10-13-review.md)" } } } diff --git a/simulations/gadm02/results/calibrated_readings.md b/simulations/gadm02/results/calibrated_readings.md index f892ca2..9697ec4 100644 --- a/simulations/gadm02/results/calibrated_readings.md +++ b/simulations/gadm02/results/calibrated_readings.md @@ -35,14 +35,14 @@ already contains today's permissiveness). | Regime | Loop | K_Ω t5 / t25 / peak | Ȳ 0–25 | VFAC t100 | G | A | P t0 → t100 | floors broken | |---|---|---|---|---|---|---|---|---| -| J1 | off | 0.13 / 0.14 / 0.15 | 0.356 | 0.381 | 0.41 | 0.52 | 0.75 → 0.71 | P | -| J1 | on | 0.12 / 0.18 / 0.18 | 0.362 | 0.377 | 0.41 | 0.51 | 0.75 → 0.72 | P | -| J2 | off | 0.29 / 0.31 / 0.34 | 0.418 | 0.255 | 0.34 | 0.27 | 0.75 → 0.86 | P | -| J2 | on | 0.22 / 0.16 / 0.23 | 0.363 | 0.280 | 0.36 | 0.33 | 0.75 → 0.85 | P | -| J3 | off | 0.25 / 0.27 / 0.29 | 0.395 | 0.244 | 0.34 | 0.26 | 0.75 → 0.89 | P | -| J3 | on | 0.19 / 0.13 / 0.20 | 0.343 | 0.266 | 0.36 | 0.32 | 0.75 → 0.87 | P | -| J4 | off | 0.25 / 0.28 / 0.30 | 0.406 | 0.271 | 0.35 | 0.35 | 0.75 → 0.86 | P | -| J4 | on | 0.20 / 0.23 / 0.25 | 0.382 | 0.279 | 0.35 | 0.37 | 0.75 → 0.85 | P | +| J1 | off | 0.13 / 0.14 / 0.14 | 0.219 | 0.342 | 0.41 | 0.52 | 0.75 → 0.71 | P | +| J1 | on | 0.12 / 0.18 / 0.18 | 0.223 | 0.338 | 0.41 | 0.51 | 0.75 → 0.72 | P | +| J2 | off | 0.29 / 0.31 / 0.34 | 0.256 | 0.229 | 0.34 | 0.27 | 0.75 → 0.86 | P | +| J2 | on | 0.22 / 0.16 / 0.23 | 0.224 | 0.253 | 0.36 | 0.33 | 0.75 → 0.85 | P | +| J3 | off | 0.25 / 0.27 / 0.29 | 0.243 | 0.220 | 0.33 | 0.26 | 0.75 → 0.89 | P | +| J3 | on | 0.19 / 0.13 / 0.20 | 0.212 | 0.242 | 0.35 | 0.32 | 0.75 → 0.88 | P | +| J4 | off | 0.25 / 0.28 / 0.30 | 0.249 | 0.243 | 0.34 | 0.35 | 0.75 → 0.86 | P | +| J4 | on | 0.20 / 0.23 / 0.25 | 0.235 | 0.251 | 0.35 | 0.37 | 0.75 → 0.85 | P | ## Readings check @@ -50,4 +50,4 @@ already contains today's permissiveness). |---|---|---|---|---| | US | holds | **fails** | holds (-0.074, +0.041) | yes | | EU | holds | holds | holds (-0.071, +0.025) | yes | -| AR | holds | **fails** | holds (-0.121, +0.036) | yes | +| AR | holds | **fails** | holds (-0.071, +0.037) | yes | diff --git a/simulations/gadm02/results/calibrated_starts.json b/simulations/gadm02/results/calibrated_starts.json index 85f4a36..cbd0eb8 100644 --- a/simulations/gadm02/results/calibrated_starts.json +++ b/simulations/gadm02/results/calibrated_starts.json @@ -1,40 +1,40 @@ { "AR": { "init": { - "As": 0.39338136453238914, - "Aw": 0.40511361695776804, - "Cch": 0.4273843914823976, - "Cd": 0.3587407705906544, - "Cs": 0.5221043401339072, - "Cw": 0.5527861039172586, - "Dch": 0.4324721016696886, - "Dd": 0.40208384609168824, - "Ds": 0.5381858106668632, - "Dw": 0.5432637495309056, - "E": 0.5162507400717095, - "F": 0.4040863733578474, - "G": 0.3939397910097698, - "Gs": 0.3691676541584724, - "Gw": 0.40219866087736084, - "Ko": 0.11023441493770228, - "Kp": 0.48266382717035555, + "As": 0.3933826396488501, + "Aw": 0.40511492207416233, + "Cch": 0.4273843968793827, + "Cd": 0.3587407755911709, + "Cs": 0.5221045404056308, + "Cw": 0.5527863221920585, + "Dch": 0.4324721146671006, + "Dd": 0.40208384609169734, + "Ds": 0.5381858106675497, + "Dw": 0.5432637495981915, + "E": 0.23490109284472976, + "F": 0.40078098442686216, + "G": 0.3939066247514239, + "Gs": 0.3691475006850279, + "Gw": 0.4021611562408701, + "Ko": 0.11020893023626183, + "Kp": 0.48265381553022696, "Lg": 0.43, - "N": 0.4663059741677877, + "N": 0.4662972258960817, "Nch": 0.22729941048548938, "Nd": 0.09090423054953169, "Ns": 0.17049764194195746, "Nw": 0.5114005895145106, - "Pd": 0.9352292554211166, - "Pi": 0.4510842967761467, - "Plin": 0.8763314787123644, - "Pm": 0.5007341069456409, - "Pmem": 0.7802943990654635, - "Ppol": 0.5023658343796548, - "Q": 0.4899755208859503, - "S": 0.4736980855522147, + "Pd": 0.9352292483301565, + "Pi": 0.4510843433941384, + "Plin": 0.8763311191596226, + "Pm": 0.5007388296322555, + "Pmem": 0.7802943183157686, + "Ppol": 0.5023230598382163, + "Q": 0.4899756881721131, + "S": 0.4736974256876645, "Sig": 0.43, - "W": 0.25085364433836677, - "X": 0.380525692886688 + "W": 0.18659851139862596, + "X": 0.3805204281698532 }, "k": 2.0, "params": { @@ -43,10 +43,11 @@ "c_d": 0.0934, "c_i": 0.4354, "c_lin": 0.1734, - "c_m": 0.0827, + "c_m": 0.0808, "c_mem": 0.2597, - "c_pol": 0.4708, + "c_pol": 0.4631, "care_load": 0.03, + "ereg": 0.005842745098039215, "expl": 0.2, "lin_open": 0.2, "m": 0.2, diff --git a/simulations/gadm02/results/calibration.md b/simulations/gadm02/results/calibration.md index e837449..b2f2fd1 100644 --- a/simulations/gadm02/results/calibration.md +++ b/simulations/gadm02/results/calibration.md @@ -11,9 +11,9 @@ range. Adoption scaled from anchor B2 by k; t* aligned by observed growth. | US | J3 | 2.00 | 1.2 | 0.125 | 0.478 | 0.0062 | 0.387 | 0.26 | | EU | J1 | 1.54 | 0.9 | 0.092 | 0.523 | 0.0063 | 0.719 | 0.60 | | DE | J1 | 1.41 | 1.5 | 0.113 | 0.616 | 0.0066 | 0.702 | 0.60 | -| AR | J2 | 2.00 | 1.1 | 0.110 | 0.387 | 0.0500 | 0.580 | 0.60 | +| AR | J2 | 2.00 | 1.1 | 0.110 | 0.387 | 0.0058 | 0.580 | 0.60 | -**Fit summary:** 39 of 39 targets inside their range; measured targets 35 of 35. +**Fit summary:** 40 of 40 targets inside their range; measured targets 36 of 36. ## Fixed anchors aligned by growth: K_Ω level miss @@ -22,7 +22,7 @@ range. Adoption scaled from anchor B2 by k; t* aligned by observed growth. | US | cannot reach growth | K_Ω 0.055, z -0.9 | K_Ω 0.125, z +0.0 | K_Ω 0.220, z +1.3 | | EU | cannot reach growth | K_Ω 0.055, z -0.7 | K_Ω 0.125, z +0.6 | K_Ω 0.203, z +2.0 | | DE | cannot reach growth | K_Ω 0.075, z -0.6 | K_Ω 0.173, z +0.9 | K_Ω 0.353, z +3.7 | -| AR | cannot reach growth | cannot reach growth | K_Ω 0.110, z +0.0 | K_Ω 0.163, z +0.9 | +| AR | cannot reach growth | cannot reach growth | K_Ω 0.110, z +0.0 | K_Ω 0.162, z +0.9 | ## Residuals at the calibrated start @@ -83,4 +83,5 @@ range. Adoption scaled from anchor B2 by k; t* aligned by observed growth. | B | 0.49–0.61 | 0.540 | -0.17 | measured | | Sig | 0.36–0.5 | 0.430 | +0.00 | measured | | Pmem | 0.68–0.88 | 0.780 | +0.00 | measured | -| Ko_ratio_1y | 1.25–1.65 | 1.443 | -0.03 | prior | +| Ko_ratio_1y | 1.25–1.65 | 1.443 | -0.04 | prior | +| E | 0.15–0.32 | 0.235 | -0.00 | measured | diff --git a/simulations/gadm02/results/cross_border.md b/simulations/gadm02/results/cross_border.md index ee3a3ba..d9e82d3 100644 --- a/simulations/gadm02/results/cross_border.md +++ b/simulations/gadm02/results/cross_border.md @@ -16,28 +16,28 @@ at most a ≈ 0.006. Counterfactual strong rule: a 0.15. |---|---|---|---|---|---|---|---|---| | closed model, current levers | US | 0.68 → 0.79 → 0.82 | 0.88 / 0.63 / 0.90 | 0.36 | 0.253 | 0.36 | 0.32 | broken | | closed model, current levers | EU | 0.72 → 0.80 → 0.82 | 0.91 / 0.60 / 0.90 | 0.30 | 0.289 | 0.41 | 0.41 | broken | -| closed model, current levers | AR | 0.75 → 0.85 → 0.86 | 0.95 / 0.79 / 0.90 | 0.31 | 0.255 | 0.34 | 0.27 | broken | +| closed model, current levers | AR | 0.75 → 0.85 → 0.86 | 0.95 / 0.79 / 0.90 | 0.31 | 0.229 | 0.34 | 0.27 | broken | | coupled, current levers | US | 0.68 → 0.79 → 0.82 | 0.88 / 0.63 / 0.90 | 0.36 | 0.253 | 0.36 | 0.32 | broken | | coupled, current levers | EU | 0.72 → 0.80 → 0.82 | 0.88 / 0.63 / 0.91 | 0.30 | 0.281 | 0.41 | 0.42 | broken | -| coupled, current levers | AR | 0.75 → 0.81 → 0.83 | 0.88 / 0.63 / 0.90 | 0.32 | 0.269 | 0.35 | 0.27 | broken | +| coupled, current levers | AR | 0.75 → 0.81 → 0.83 | 0.88 / 0.63 / 0.90 | 0.32 | 0.241 | 0.35 | 0.27 | broken | | coupled, DMA as observed (a fitted) | US | 0.68 → 0.79 → 0.82 | 0.88 / 0.63 / 0.90 | 0.36 | 0.253 | 0.36 | 0.32 | broken | | coupled, DMA as observed (a fitted) | EU | 0.72 → 0.80 → 0.82 | 0.88 / 0.63 / 0.91 | 0.30 | 0.281 | 0.41 | 0.42 | broken | -| coupled, DMA as observed (a fitted) | AR | 0.75 → 0.81 → 0.83 | 0.88 / 0.63 / 0.90 | 0.32 | 0.269 | 0.35 | 0.27 | broken | +| coupled, DMA as observed (a fitted) | AR | 0.75 → 0.81 → 0.83 | 0.88 / 0.63 / 0.90 | 0.32 | 0.241 | 0.35 | 0.27 | broken | | coupled, strong access rule a 0.15 (σ 0) | US | 0.68 → 0.79 → 0.82 | 0.88 / 0.63 / 0.90 | 0.36 | 0.253 | 0.36 | 0.32 | broken | | coupled, strong access rule a 0.15 (σ 0) | EU | 0.72 → 0.66 → 0.68 | 0.14 / 0.07 / 0.91 | 0.34 | 0.333 | 0.44 | 0.39 | ok | -| coupled, strong access rule a 0.15 (σ 0) | AR | 0.75 → 0.81 → 0.83 | 0.88 / 0.63 / 0.90 | 0.32 | 0.269 | 0.35 | 0.27 | broken | +| coupled, strong access rule a 0.15 (σ 0) | AR | 0.75 → 0.81 → 0.83 | 0.88 / 0.63 / 0.90 | 0.32 | 0.241 | 0.35 | 0.27 | broken | | coupled, strong access rule, spillover σ 0.5 | US | 0.68 → 0.70 → 0.75 | 0.68 / 0.12 / 0.90 | 0.38 | 0.279 | 0.37 | 0.31 | broken | | coupled, strong access rule, spillover σ 0.5 | EU | 0.72 → 0.66 → 0.68 | 0.14 / 0.07 / 0.91 | 0.34 | 0.332 | 0.44 | 0.39 | ok | -| coupled, strong access rule, spillover σ 0.5 | AR | 0.75 → 0.73 → 0.76 | 0.68 / 0.12 / 0.90 | 0.34 | 0.298 | 0.36 | 0.26 | broken | +| coupled, strong access rule, spillover σ 0.5 | AR | 0.75 → 0.73 → 0.76 | 0.68 / 0.12 / 0.90 | 0.33 | 0.265 | 0.36 | 0.26 | broken | | coupled, US moves to J1 levers | US | 0.68 → 0.58 → 0.60 | 0.86 / 0.02 / 0.28 | 0.49 | 0.379 | 0.46 | 0.47 | ok | | coupled, US moves to J1 levers | EU | 0.72 → 0.62 → 0.63 | 0.86 / 0.02 / 0.35 | 0.37 | 0.359 | 0.45 | 0.38 | ok | -| coupled, US moves to J1 levers | AR | 0.75 → 0.63 → 0.66 | 0.86 / 0.02 / 0.28 | 0.37 | 0.344 | 0.38 | 0.25 | ok | +| coupled, US moves to J1 levers | AR | 0.75 → 0.63 → 0.66 | 0.86 / 0.02 / 0.28 | 0.37 | 0.303 | 0.37 | 0.25 | ok | | coupled, US J1 + DMA as observed | US | 0.68 → 0.58 → 0.60 | 0.86 / 0.02 / 0.28 | 0.49 | 0.379 | 0.46 | 0.47 | ok | | coupled, US J1 + DMA as observed | EU | 0.72 → 0.62 → 0.63 | 0.86 / 0.02 / 0.35 | 0.37 | 0.359 | 0.45 | 0.38 | ok | -| coupled, US J1 + DMA as observed | AR | 0.75 → 0.63 → 0.66 | 0.86 / 0.02 / 0.28 | 0.37 | 0.344 | 0.38 | 0.25 | ok | +| coupled, US J1 + DMA as observed | AR | 0.75 → 0.63 → 0.66 | 0.86 / 0.02 / 0.28 | 0.37 | 0.303 | 0.37 | 0.25 | ok | | coupled, US J1 + strong access rule | US | 0.68 → 0.58 → 0.60 | 0.86 / 0.02 / 0.28 | 0.49 | 0.379 | 0.46 | 0.47 | ok | | coupled, US J1 + strong access rule | EU | 0.72 → 0.47 → 0.42 | 0.15 / 0.01 / 0.35 | 0.41 | 0.426 | 0.51 | 0.35 | ok | -| coupled, US J1 + strong access rule | AR | 0.75 → 0.63 → 0.66 | 0.86 / 0.02 / 0.28 | 0.37 | 0.344 | 0.38 | 0.25 | ok | +| coupled, US J1 + strong access rule | AR | 0.75 → 0.63 → 0.66 | 0.86 / 0.02 / 0.28 | 0.37 | 0.303 | 0.37 | 0.25 | ok | ## EU domination at t 100: effect of each lever (coupled model) diff --git a/simulations/gadm02/results/world_scenarios.md b/simulations/gadm02/results/world_scenarios.md new file mode 100644 index 0000000..4c7004a --- /dev/null +++ b/simulations/gadm02/results/world_scenarios.md @@ -0,0 +1,80 @@ +# GADM-0.4: global scenarios with cross-border coupling + +Generated by `simulations/gadm02/world_scenarios.py` (ASSEMBLY-WP-0011-T04/T05). +Calibration v0.4 starts; operators' home US; J4 reference bloc competes for the frontier. +Ȳ = mean potential output Y* relative to the jurisdiction's own Y* at t 0 (1.00 = no growth); +output levels are normalized model units and not comparable across jurisdictions. P floor 0.70. + +## X1 US-led concentrated frontier + +| Loop | Jurisdiction | K_Ω t10 | Ȳ 0–25 / 0–100 | VFAC t100 | P t100 | G | A | Σ end | +|---|---|---|---|---|---|---|---|---| +| off | US | 0.39 | 1.04 / 0.87 | 0.253 | 0.82 | 0.36 | 0.32 | 0.28 | +| off | EU | 0.31 | 1.01 / 0.85 | 0.281 | 0.82 | 0.41 | 0.41 | 0.54 | +| off | AR | 0.34 | 0.99 / 0.81 | 0.241 | 0.83 | 0.35 | 0.27 | 0.43 | +| off | J4 | 0.40 | 1.07 / 0.92 | 0.285 | 0.77 | 0.38 | 0.41 | 0.28 | +| on | US | 0.21 | 0.88 / 0.68 | 0.295 | 0.77 | 0.39 | 0.39 | 0.37 | +| on | EU | 0.28 | 0.96 / 0.76 | 0.311 | 0.77 | 0.42 | 0.46 | 0.40 | +| on | AR | 0.25 | 0.89 / 0.68 | 0.275 | 0.78 | 0.37 | 0.31 | 0.38 | +| on | J4 | 0.23 | 0.96 / 0.84 | 0.297 | 0.76 | 0.39 | 0.43 | 0.45 | + +## X2 open-lineage world + +| Loop | Jurisdiction | K_Ω t10 | Ȳ 0–25 / 0–100 | VFAC t100 | P t100 | G | A | Σ end | +|---|---|---|---|---|---|---|---|---| +| off | US | 0.45 | 1.16 / 1.10 | 0.379 | 0.60 | 0.46 | 0.47 | 0.28 | +| off | EU | 0.34 | 1.09 / 1.01 | 0.359 | 0.63 | 0.45 | 0.38 | 0.54 | +| off | AR | 0.37 | 1.06 / 0.93 | 0.303 | 0.66 | 0.37 | 0.25 | 0.43 | +| off | J4 | 0.40 | 1.07 / 0.92 | 0.285 | 0.77 | 0.38 | 0.41 | 0.28 | +| on | US | 0.33 | 1.10 / 1.07 | 0.398 | 0.56 | 0.48 | 0.48 | 0.47 | +| on | EU | 0.33 | 1.06 / 0.97 | 0.379 | 0.60 | 0.46 | 0.40 | 0.43 | +| on | AR | 0.29 | 0.98 / 0.85 | 0.332 | 0.62 | 0.40 | 0.28 | 0.38 | +| on | J4 | 0.23 | 0.96 / 0.84 | 0.297 | 0.76 | 0.39 | 0.43 | 0.45 | + +## X3 accelerating frontier + +| Loop | Jurisdiction | K_Ω t10 | Ȳ 0–25 / 0–100 | VFAC t100 | P t100 | G | A | Σ end | +|---|---|---|---|---|---|---|---|---| +| off | US | 0.73 | 1.32 / 1.20 | 0.218 | 0.84 | 0.33 | 0.23 | 0.28 | +| off | EU | 0.39 | 1.08 / 0.95 | 0.267 | 0.84 | 0.40 | 0.38 | 0.54 | +| off | AR | 0.41 | 1.06 / 0.89 | 0.226 | 0.85 | 0.34 | 0.24 | 0.43 | +| off | J4 | 0.74 | 1.33 / 1.23 | 0.246 | 0.80 | 0.35 | 0.31 | 0.28 | +| on | US | 0.30 | 0.93 / 0.72 | 0.290 | 0.78 | 0.39 | 0.38 | 0.34 | +| on | EU | 0.28 | 0.99 / 0.82 | 0.306 | 0.78 | 0.42 | 0.43 | 0.38 | +| on | AR | 0.25 | 0.93 / 0.73 | 0.269 | 0.78 | 0.37 | 0.30 | 0.34 | +| on | J4 | 0.37 | 1.12 / 1.03 | 0.275 | 0.78 | 0.37 | 0.37 | 0.40 | + +## X4 fragmented blocs + +| Loop | Jurisdiction | K_Ω t10 | Ȳ 0–25 / 0–100 | VFAC t100 | P t100 | G | A | Σ end | +|---|---|---|---|---|---|---|---|---| +| off | US | 0.39 | 1.04 / 0.87 | 0.253 | 0.82 | 0.36 | 0.32 | 0.28 | +| off | EU | 0.30 | 1.00 / 0.84 | 0.282 | 0.83 | 0.41 | 0.42 | 0.54 | +| off | AR | 0.34 | 0.99 / 0.80 | 0.235 | 0.85 | 0.34 | 0.27 | 0.43 | +| off | J4 | 0.40 | 1.07 / 0.92 | 0.285 | 0.77 | 0.38 | 0.41 | 0.28 | +| on | US | 0.21 | 0.88 / 0.68 | 0.295 | 0.77 | 0.39 | 0.39 | 0.37 | +| on | EU | 0.27 | 0.94 / 0.72 | 0.307 | 0.79 | 0.42 | 0.47 | 0.41 | +| on | AR | 0.24 | 0.87 / 0.64 | 0.267 | 0.81 | 0.37 | 0.33 | 0.39 | +| on | J4 | 0.23 | 0.96 / 0.84 | 0.297 | 0.76 | 0.39 | 0.43 | 0.45 | + +## Hypothesis re-test + +| Context | Loop | H1 EU adoption lags US and AR (K_Ω t10) | EU − US: ΔȲ 0–25 / ΔVFAC | H2 AR − EU: ΔȲ 0–25 / ΔȲ 0–100 / ΔVFAC | H2 holds? | +|---|---|---|---|---|---| +| X1 US-led concentrated frontier | off | yes (0.31 vs 0.39, 0.34) | -0.031 / +0.028 | -0.016 / -0.040 / -0.041 | no | +| X1 US-led concentrated frontier | on | no (0.28 vs 0.21, 0.25) | +0.075 / +0.016 | -0.066 / -0.079 / -0.036 | no | +| X2 open-lineage world | off | yes (0.34 vs 0.45, 0.37) | -0.074 / -0.020 | -0.028 / -0.083 / -0.055 | no | +| X2 open-lineage world | on | no (0.33 vs 0.33, 0.29) | -0.039 / -0.018 | -0.074 / -0.122 / -0.048 | no | +| X3 accelerating frontier | off | yes (0.39 vs 0.73, 0.41) | -0.235 / +0.049 | -0.024 / -0.052 / -0.041 | no | +| X3 accelerating frontier | on | no (0.28 vs 0.30, 0.25) | +0.058 / +0.016 | -0.063 / -0.086 / -0.037 | no | +| X4 fragmented blocs | off | yes (0.30 vs 0.39, 0.34) | -0.038 / +0.029 | -0.016 / -0.044 / -0.047 | no | +| X4 fragmented blocs | on | no (0.27 vs 0.21, 0.24) | +0.060 / +0.012 | -0.073 / -0.080 / -0.040 | no | + +## Local-in-context vs. global (EU, context X1, loop off) + +EU simulated alone against a US path from a US-only run, compared with the full global run. + +| Setting | EU P t100 local | global | EU K_Ω t25 local | global | max |ΔP| over time | +|---|---|---|---|---|---| +| no spillover | 0.821 | 0.821 | 0.303 | 0.303 | 0.000 | +| strong EU access rule, spillover σ 0.5 | 0.683 | 0.684 | 0.340 | 0.340 | 0.000 | diff --git a/simulations/gadm02/test_world.py b/simulations/gadm02/test_world.py index 61cb041..05149ad 100644 --- a/simulations/gadm02/test_world.py +++ b/simulations/gadm02/test_world.py @@ -57,6 +57,15 @@ class TestWorld(unittest.TestCase): self.assertGreater(lag1["lag"][-1]["Ko"], lag0["lag"][-1]["Ko"]) self.assertEqual(lag1["lead"][-1]["Ko"], lag0["lead"][-1]["Ko"]) + def test_local_in_context_reproduces_global(self): + f = {c: 1.0 for c in w.COUPLED} + glob = w.simulate_world({"home": w.make({"m": 0.2}), "host": w.make({"m": 0.7}, home="home", f=f, kappa=0.5)}, + T=T, record_every=1) + local = w.simulate_world({"home": w.context(glob["home"], {"m": 0.2}), + "host": w.make({"m": 0.7}, home="home", f=f, kappa=0.5)}, T=T, record_every=1) + for k in ("Ko", "P", "Pd", "VFAC"): + self.assertAlmostEqual(local["host"][-1][k], glob["host"][-1][k], places=9, msg=k) + if __name__ == "__main__": unittest.main() diff --git a/simulations/gadm02/world.py b/simulations/gadm02/world.py index c0446ea..d639639 100644 --- a/simulations/gadm02/world.py +++ b/simulations/gadm02/world.py @@ -16,6 +16,9 @@ Dynamics: - frontier access: organism learning uses max(K_Omega^j, kappa * frontier). Synchronous step: every jurisdiction reads the previous state of all others. +A jurisdiction made with `context(rows)` is not simulated: its state follows +given rows (one per time step), for local runs in a context scenario +(models/CrossBorder.md § 3.6). With f = 0, kappa = 0 and a = 0 each jurisdiction reproduces gadm04.simulate exactly (test_world.py). """ @@ -45,6 +48,15 @@ def make(params: dict | None = None, init: dict | None = None, home: str | None "access": {c: 0.0 for c in COUPLED} | (access or {}), "kappa": kappa} +def context(rows: list[dict], params: dict | None = None) -> dict: + """A rest-of-world jurisdiction whose state follows `rows` (recorded every step).""" + s = {k: rows[0][k] for k in g.STOCKS + tuple(OP.values()) if k in rows[0]} + for c in COUPLED: + s.setdefault(OP[c], s[c]) + return {"p": {**g.PARAMS, **(params or {})}, "s": s, "home": None, "f": {c: 0.0 for c in COUPLED}, + "access": {c: 0.0 for c in COUPLED}, "kappa": 0.0, "path": rows} + + def mixed(j: dict) -> dict: s = dict(j["s"]) for c in COUPLED: @@ -112,6 +124,9 @@ def simulate_world(world: dict, T: float = 100.0, dt: float = 0.1, record_every: j["p"] = {**j["p"], "sig_pb0": g.perceived_benefit(mixed(j), a0, g.legislated(mixed(j), j["p"]))} keys = g.STOCKS + tuple(OP.values()) rows = {k: [] for k in world} + for j in world.values(): + if j.get("path") and record_every and len(j["path"]) < int(round(T / dt)) + 1: + raise ValueError("context rows must be recorded every step (record_every=1) and cover T") steps = int(round(T / dt)) for i in range(steps + 1): der = step_derivatives(world, sigma) @@ -125,6 +140,10 @@ def simulate_world(world: dict, T: float = 100.0, dt: float = 0.1, record_every: rows[name].append(row) if i < steps: for name, (d, _a, _sm) in der.items(): + if world[name].get("path"): + row = world[name]["path"][min(i + 1, len(world[name]["path"]) - 1)] + world[name]["s"] = {k: row.get(k, world[name]["s"][k]) for k in world[name]["s"]} + continue s = world[name]["s"] world[name]["s"] = {k: (max(0.0, s[k] + dt * d[k]) if k.startswith("N") else min(1.0, max(0.0, s[k] + dt * d[k]))) for k in keys} diff --git a/simulations/gadm02/world_scenarios.py b/simulations/gadm02/world_scenarios.py new file mode 100644 index 0000000..926de64 --- /dev/null +++ b/simulations/gadm02/world_scenarios.py @@ -0,0 +1,132 @@ +"""Global and local-in-context scenarios; hypothesis re-test (ASSEMBLY-WP-0011-T04/T05). + +World: US (operators' home, calibrated, J3-like levers), EU (calibrated, J1), +AR (calibrated, J2) and a J4 reference bloc "J4" (US calibrated start with J4 +levers and its own operators; it competes for the frontier only). + +Context scenarios (rest of the world as seen by EU and AR; T04): + X1 US-led concentrated frontier current levers + X2 open-lineage world US moves to rights-first (J1) levers + X3 accelerating frontier US and J4 with self-enhancement (selfenh 3, B4-like) + X4 fragmented blocs hosts' frontier access 0.2, foreign shares halved + +Hypotheses (owner, research/ScenarioBandMethod.md § 4): + H1 "Europe lags": EU adoption below US and AR; is lagging worse for output or VFAC? + H2 "Argentina may thrive": AR output and VFAC above EU? + +Local vs. global: EU run alone against a US context path taken from a US-only +run, compared with the global run. The approximation fails when the host feeds +back on the home (spillover, frontier). + +Usage: python3 -B simulations/gadm02/world_scenarios.py +""" + +from __future__ import annotations + +import sys +from pathlib import Path + +sys.dont_write_bytecode = True + +import cross_border as cb # noqa: E402 +import gadm04 as g # noqa: E402 +import world as w # noqa: E402 +from jurisdictions import ARCHETYPES # noqa: E402 + +OUT = Path(__file__).resolve().parent / "results" +J1 = cb.J1 +J4 = {k: v for k, v in ARCHETYPES["J4"][1].items() if k != "perm"} +CONTEXTS = { + "X1 US-led concentrated frontier": {}, + "X2 open-lineage world": {"us": J1}, + "X3 accelerating frontier": {"us": {"selfenh": 3.0}, "j4": {"selfenh": 3.0}}, + "X4 fragmented blocs": {"kappa": 0.2, "fscale": 0.5}, +} +NAMES = ("US", "EU", "AR", "J4") + + +def build(cal: dict, ctx: dict, sent: float) -> dict: + us_p, us_s = cal["US"] + eu_p, eu_s = cal["EU"] + ar_p, ar_s = cal["AR"] + kap = ctx.get("kappa", cb.KAPPA) + fs = ctx.get("fscale", 1.0) + f_eu = {c: v * fs for c, v in cb.F["EU"].items()} + f_ar = {c: v * fs for c, v in cb.F["AR"].items()} + return { + "US": w.make({**us_p, **ctx.get("us", {}), "sent": sent}, us_s), + "EU": w.make({**eu_p, "sent": sent}, eu_s, home="US", f=f_eu, kappa=kap), + "AR": w.make({**ar_p, "sent": sent}, ar_s, home="US", f=f_ar, kappa=kap), + "J4": w.make({**us_p, **J4, **ctx.get("j4", {}), "sent": sent, "sig_gain": 0.5, "leg_lag": 10.0}, us_s), + } + + +def summ(rows: list[dict]) -> dict: + f = rows[-1] + y0 = rows[0]["Ystar"] # output relative to the jurisdiction's own start (levels are not comparable) + return {"Ko10": rows[10]["Ko"], "Y25": sum(r["Ystar"] for r in rows[:26]) / 26 / y0, + "Y100": sum(r["Ystar"] for r in rows) / len(rows) / y0, "V100": f["VFAC"], "P": f["P"], + "G": f["G"], "A": f["A"], "Sig": f["Sig"]} + + +def main() -> None: + OUT.mkdir(exist_ok=True) + cal = cb.base() + lines = [f"# {g.MODEL_VERSION}: global scenarios with cross-border coupling", "", + "Generated by `simulations/gadm02/world_scenarios.py` (ASSEMBLY-WP-0011-T04/T05).", + "Calibration v0.4 starts; operators' home US; J4 reference bloc competes for the frontier.", + "Ȳ = mean potential output Y* relative to the jurisdiction's own Y* at t 0 (1.00 = no growth);", + "output levels are normalized model units and not comparable across jurisdictions. P floor 0.70.", ""] + res = {} + for cname, ctx in CONTEXTS.items(): + for lp, sent in (("off", 0.0), ("on", 1.0)): + rows = w.simulate_world(build(cal, ctx, sent)) + for n in NAMES: + res[(cname, lp, n)] = summ(rows[n]) + for cname in CONTEXTS: + lines += [f"## {cname}", "", + "| Loop | Jurisdiction | K_Ω t10 | Ȳ 0–25 / 0–100 | VFAC t100 | P t100 | G | A | Σ end |", + "|---|---|---|---|---|---|---|---|---|"] + for lp in ("off", "on"): + for n in NAMES: + r = res[(cname, lp, n)] + lines.append(f"| {lp} | {n} | {r['Ko10']:.2f} | {r['Y25']:.2f} / {r['Y100']:.2f} | {r['V100']:.3f}" + f" | {r['P']:.2f} | {r['G']:.2f} | {r['A']:.2f} | {r['Sig']:.2f} |") + lines.append("") + + lines += ["## Hypothesis re-test", "", + "| Context | Loop | H1 EU adoption lags US and AR (K_Ω t10) | EU − US: ΔȲ 0–25 / ΔVFAC | " + "H2 AR − EU: ΔȲ 0–25 / ΔȲ 0–100 / ΔVFAC | H2 holds? |", "|---|---|---|---|---|---|"] + for cname in CONTEXTS: + for lp in ("off", "on"): + eu, us, ar = (res[(cname, lp, n)] for n in ("EU", "US", "AR")) + lags = eu["Ko10"] < us["Ko10"] and eu["Ko10"] < ar["Ko10"] + h2 = ar["Y100"] > eu["Y100"] and ar["V100"] > eu["V100"] + lines.append(f"| {cname} | {lp} | {'yes' if lags else 'no'} ({eu['Ko10']:.2f} vs {us['Ko10']:.2f}, " + f"{ar['Ko10']:.2f}) | {eu['Y25'] - us['Y25']:+.3f} / {eu['V100'] - us['V100']:+.3f} | " + f"{ar['Y25'] - eu['Y25']:+.3f} / {ar['Y100'] - eu['Y100']:+.3f} / {ar['V100'] - eu['V100']:+.3f}" + f" | {'yes' if h2 else 'no'} |") + + lines += ["", "## Local-in-context vs. global (EU, context X1, loop off)", "", + "EU simulated alone against a US path from a US-only run, compared with the full global run.", "", + "| Setting | EU P t100 local | global | EU K_Ω t25 local | global | max |ΔP| over time |", + "|---|---|---|---|---|---|"] + for label, eu_access, sigma in (("no spillover", None, None), + ("strong EU access rule, spillover σ 0.5", cb.STRONG, {"Pd": 0.5, "Pmem": 0.5})): + wd = build(cal, {}, 0.0) + wd["EU"]["access"] = {c: 0.0 for c in w.COUPLED} | (eu_access or {}) + glob = w.simulate_world(wd, record_every=1, sigma=sigma) + us_only = w.simulate_world({"US": wd["US"], "J4": wd["J4"]}, record_every=1) + loc = w.simulate_world({"US": w.context(us_only["US"], wd["US"]["p"]), + "J4": w.context(us_only["J4"], wd["J4"]["p"]), "EU": wd["EU"]}, + record_every=1, sigma=sigma) + dmax = max(abs(a["P"] - b["P"]) for a, b in zip(loc["EU"], glob["EU"])) + lines.append(f"| {label} | {loc['EU'][-1]['P']:.3f} | {glob['EU'][-1]['P']:.3f} | {loc['EU'][250]['Ko']:.3f}" + f" | {glob['EU'][250]['Ko']:.3f} | {dmax:.3f} |") + lines.append("") + (OUT / "world_scenarios.md").write_text("\n".join(lines)) + print("\n".join(lines)) + + +if __name__ == "__main__": + main() diff --git a/workplans/ASSEMBLY-WP-0011-cross-border-coupling.md b/workplans/ASSEMBLY-WP-0011-cross-border-coupling.md index ef41981..15361bf 100644 --- a/workplans/ASSEMBLY-WP-0011-cross-border-coupling.md +++ b/workplans/ASSEMBLY-WP-0011-cross-border-coupling.md @@ -4,7 +4,7 @@ type: workplan title: "Cross-border coupling: jurisdiction-local and global scenarios" domain: communication repo: assembly-economics -status: active +status: finished flavor: implementation depends_on: [ASSEMBLY-WP-0013, ASSEMBLY-WP-0015] owner: claude-code @@ -116,11 +116,13 @@ jurisdictions equals one jurisdiction; conservation of shared quantities. ```task id: ASSEMBLY-WP-0011-T04 -status: todo +status: done priority: medium state_hub_task_id: "a2f54c16-5f7f-53b4-ae95-7d4bb8d52c4a" ``` +**Done 2026-10-13:** `world.context()` for local runs; contexts X1–X4 (`models/CrossBorder.md` § 5). + Define rest-of-world context scenarios (for example: "US-led concentrated frontier", "open-lineage world", "fragmented blocs") as exogenous paths of the coupled quantities, derived from global runs or set by hand. A local @@ -130,12 +132,12 @@ run is one jurisdiction × one context × one band anchor. ```task id: ASSEMBLY-WP-0011-T05 -status: progress +status: done priority: high state_hub_task_id: "8b1f4c24-60e6-5d13-89ef-de6416795a70" ``` -**First part done 2026-10-13:** BR-007 test (`cross_border.py`, `models/CrossBorder.md` § 4, BR-008). Still open: the J4 bloc, the B2–B4 band, the legitimacy loop, and the hypothesis re-test. +**Done 2026-10-13:** BR-007 test (§ 4, BR-008) and hypothesis re-test (`world_scenarios.py`, § 5). H1 holds only without the legitimacy loop; H2 is not supported in any context. Local runs reproduce global runs for host outcomes. The B4 stress case is context X3. Run EU, US, AR (and a J4 reference bloc) together from the calibrated starts, across B2–B3 (the band the data supports) plus B4 as a stress case, @@ -160,3 +162,10 @@ Add indicators for the coupling weights to the catalog (lineage origin of deployed models, cloud and platform market shares by jurisdiction, AI trade and investment flows), so that the matrix can be updated from checkpoints (WP-0010). + +## Close-out 2026-10-13 + +T01–T06 are done (`models/CrossBorder.md`, `world.py`, `cross_border.py`, +`world_scenarios.py`, BR-008). The residuals are handed off to +ASSEMBLY-WP-0016: lineage access rules, endogenous foreign shares, calibration +of κ and the J4 bloc, and channels C6–C8. diff --git a/workplans/ASSEMBLY-WP-0016-open-economy-refinements.md b/workplans/ASSEMBLY-WP-0016-open-economy-refinements.md new file mode 100644 index 0000000..0d6f07f --- /dev/null +++ b/workplans/ASSEMBLY-WP-0016-open-economy-refinements.md @@ -0,0 +1,75 @@ +--- +id: ASSEMBLY-WP-0016 +type: workplan +title: "Open-economy refinements: lineage access rules, endogenous foreign shares, calibrated coupling" +domain: communication +repo: assembly-economics +status: proposed +flavor: residual +depends_on: [ASSEMBLY-WP-0011] +owner: claude-code +topic_slug: coulomb-social +created: "2026-10-13" +updated: "2026-10-13" +--- + +# Open-economy refinements + +Residuals of ASSEMBLY-WP-0011 (`models/CrossBorder.md` §§ 4–5). The coupled +model explains BR-007 and re-tests the owner hypotheses. These refinements +decide how far its readings can be trusted. + +## Lineage access rules + +```task +id: ASSEMBLY-WP-0016-T01 +status: todo +priority: high +``` + +No host rule reaches imported lineages (BR-008, linked to BR-003). Model a +host lineage rule: model portability and interoperability duties that lower +the foreign operator part of Plin and raise the effective `lin_open`. Calibrate +its plausible strength from evidence (for example open-weight adoption shares +after interoperability rules, or the AI Act's GPAI obligations). Re-run +`cross_border.py`: can a host reach Plin without the home's cooperation? + +## Endogenous foreign shares + +```task +id: ASSEMBLY-WP-0016-T02 +status: todo +priority: medium +``` + +Make f_c^j a state: it falls when domestic alternatives grow (domestic X, +N, open lineages) or access rules bind, and rises with the operator's +quality lead (frontier gap). Check that today's measured f (§ 2) is a rest +point. Use indicator CB1 (operator shares over time) to calibrate the speed. + +## Calibrate frontier access and the J4 bloc + +```task +id: ASSEMBLY-WP-0016-T03 +status: todo +priority: medium +``` + +κ = 0.8 is a prior. Calibrate it from the lag between frontier releases and +host adoption (indicator CB5, BTOS vs. Eurostat timing). Give the J4 bloc its +own calibrated start (adoption, concentration, sentiment) instead of the US +start with J4 levers. + +## Trade, talent and sentiment channels + +```task +id: ASSEMBLY-WP-0016-T04 +status: todo +priority: low +``` + +Add C6 (trade in organism output), C7 (talent and founders) and C8 +(sentiment contagion) only where a reading depends on them. First check +whether H2 ("Argentina may thrive") changes with an export channel. That is +the strongest argument for J2-type thriving that the model does not yet +represent (`models/AdoptionBand.md` § 4.5).