ASSEMBLY-WP-0005-T06: life-cycle cohorts; finish WP-0005; add WP-0006

- gadm03c.py: four cohorts with demography, cohort capability, mentoring,
  care load on attention; stationary at replacement fertility (tested)
- life_cycle.py: L1 supported after fixing an inert mentoring term; L2
  conditional on who carries care per person, care relief via participation
  claims protects carers' attention; L3 not supported (H lacks a durable
  component)
- GADM-0.3.md complete; ASSEMBLY-WP-0006 (GADM-0.4, proposed residual)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1494246@bnt-lap001
Assistant-Session: caf6de6f-f9e4-47ce-a584-49baa271fa4b
This commit is contained in:
tegwick 2026-10-12 07:38:22 +02:00
parent 7707657464
commit b6a0d7b3ff
12 changed files with 543 additions and 12 deletions

View file

@ -2,16 +2,15 @@
# Custodian Brief — assembly-economics
**Domain:** communication
**Last synced:** 2026-10-12 05:33 UTC
**Last synced:** 2026-10-12 05:35 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
### GADM-0.3: global sensitivity, power channels, cohorts
Progress: 4/6 done | workplan_id: `23e33ee7-cb27-52bc-819c-704f44f91663`
Progress: 5/6 done | workplan_id: `23e33ee7-cb27-52bc-819c-704f44f91663`
**Open tasks:**
- · Strengthen attention dynamics and the full organism grid `f56e20b4`
- · Life-cycle cohorts `2b749127`
## Inbox Hygiene

View file

@ -23,6 +23,7 @@ cd simulations/gadm02 && python3 gsa.py # global sensitivity, ~5 min
cd simulations/gadm02 && python3 -B power_channels.py # GADM-0.3 power channels (T03 stage)
cd simulations/gadm02 && python3 -B wealth.py # GADM-0.3 wealth vs. power
cd simulations/gadm02 && python3 -B organism_grid.py # GADM-0.3 organism grid
cd simulations/gadm02 && python3 -B life_cycle.py # GADM-0.3 cohorts
```
Use `python3 -B` after quick edits; a stale bytecode cache once masked a change.

View file

@ -44,5 +44,5 @@
| task | ASSEMBLY-WP-0005-T02 | done | — | workplans/ASSEMBLY-WP-0005-gadm-0.3.md |
| task | ASSEMBLY-WP-0005-T03 | done | — | workplans/ASSEMBLY-WP-0005-gadm-0.3.md |
| task | ASSEMBLY-WP-0005-T04 | done | — | workplans/ASSEMBLY-WP-0005-gadm-0.3.md |
| task | ASSEMBLY-WP-0005-T05 | todo | — | workplans/ASSEMBLY-WP-0005-gadm-0.3.md |
| task | ASSEMBLY-WP-0005-T05 | done | — | workplans/ASSEMBLY-WP-0005-gadm-0.3.md |
| task | ASSEMBLY-WP-0005-T06 | todo | — | workplans/ASSEMBLY-WP-0005-gadm-0.3.md |

View file

@ -6,10 +6,10 @@ the code is the reference if the two ever disagree.
# Generative Assembly Dynamics Model — GADM-0.3
**Status:** in progress, exploratory. Implemented so far: power channels
(§ 2, ASSEMBLY-WP-0005-T03), wealth separated from power (§ 3, T04),
attention recalibration and the organism grid (§ 4, T05). Planned: cohorts
(T06).
**Status:** complete for ASSEMBLY-WP-0005, exploratory. Power channels
(§ 2, T03), wealth separated from power (§ 3, T04), attention recalibration
and organism grid (§ 4, T05), life-cycle cohorts (§ 5, T06). Open items are
in § 6 and ASSEMBLY-WP-0006.
GADM-0.3 builds on GADM-0.2 (`GADM-0.2.md`). Everything not described here is
unchanged; the implementation reuses `gadm02.py`. Time unit: one year.
@ -343,6 +343,106 @@ background reproduces the generative regime exactly (VFAC 0.672).
stays at about 0.6, because it depends on discovery concentration, which
is not an organism lever.
---
## 5. Life-cycle cohorts (T06)
Implemented in `simulations/gadm02/gadm03c.py` on top of the full GADM-0.3.
### 5.1 Structure
| Cohort | Ages | Carries | Notes |
|---|---|---|---|
| children `ch` | 0–19 | H | education, adult attention as care input, seniors' mentoring |
| working age `w` | 20–64 | H, A | GADM-0.2 learning; deskilling; mentoring inflow T_g; main care provider |
| seniors `s` | 65–79 | H, A | half learning rate, 1.5× depreciation; provides a share of care |
| very old `d` | 80+ | H | 3× depreciation; main care need |
Population counts follow births (`birth` × N_w) and ageing rates of 1/20,
1/45 and 1/15 per year, with deaths of the very old at 1/8 per year. At
`birth` = 1/45 (replacement), the age structure is stationary at about
23 / 51 / 17 / 9 %. A unit test checks this.
Aggregates passed to the rest of the model: H is population-weighted over all
cohorts; A is weighted over working age and seniors. G remains a single
aggregate.
Care need = 0.5 × share of children + 1.0 × share of very old. Its attention
cost is split between working age and seniors (`care_sen`), and reduced by
participation claims: relief = 1 − 3 × cp.
### 5.2 Effect on the scenarios
With cohorts, the baseline VFAC is 0.323 (0.334 without cohorts) and the
generative regime 0.656 (0.672). Capability and attention are a little lower,
because of senior depreciation and care load. The scenario ordering is
unchanged.
### 5.3 Hypotheses L1–L3
Full tables: `simulations/gadm02/results/life_cycle.md`.
**L1: strong intergenerational transfer lets an ageing society keep H.
Supported.**
| Demography | T_g = 0 | T_g = 0.05 | T_g = 0.15 |
|---|---|---|---|
| stable (ΔH over 100 years) | −0.043 | −0.032 | −0.011 |
| ageing, births at 75 % of replacement | −0.053 | −0.040 | −0.018 |
An ageing society with strong mentoring loses less capability than a stable
society without it. A first formulation of T_g, which transferred only
max(0, H_s − H_w), was inert because senior capability decays below
working-age capability. It was replaced by an inflow proportional to senior
capability and working-age headroom.
**L2: without recognized care participation, A falls fastest in the
working-age cohort. Conditionally supported.** Attention is lowest in
whichever cohort carries the higher care load *per person*:
- with seniors providing 10 % of care, working-age A is lowest (0.40 vs. 0.44);
- with 30 %, senior A is lowest (0.40 vs. 0.42), because there are fewer
seniors to share it.
Care relief through participation claims (cp = 0.15) raises working-age
attention by 0.034–0.042 in every setting. So the post-work participation
channel directly protects the attention of carers.
**L3: education reaches working-age capability with a 15–20 year lag. Not
supported in this model.** Raising education intensity by 50 % raises
children's capability by +0.067, but working-age capability only by +0.010,
with half of the effect reached after about 9 years. The cause is structural:
working-age capability relaxes to its own conditions within roughly 8 years
(adult learning and depreciation rates). That washes out the cohort inflow,
so H has almost no memory of childhood. Human-capital research generally
finds persistent effects of early education, so this points to a missing
mechanism, not an empirical result. The fix belongs in GADM-0.4: split H
into a durable, education-formed component and a current component.
### 5.4 Further observations
- **Ageing is slow in this demography.** At 75 % of replacement fertility,
the share of seniors and very old rises only from 0.26 to 0.29 in 100 years,
and total care need barely changes (fewer children offset more very old at
the chosen weights).
- **Aggregate H declines at baseline even with stationary demography**
(−0.043), because of senior and very-old depreciation, which the
single-population model did not have.
---
## 6. Open items (handed to ASSEMBLY-WP-0006)
- Split H into durable and current components (L3).
- Agency G per cohort.
- Initialise W and the cohort attention stocks at their own equilibria (§ 3.4
reading 3, § 5.3 L2 note).
- Estimates instead of assumptions for the channel self-reinforcement r_k, the
wealth conversion k_w, and organism depreciation `dO` (the top driver in the
GADM-0.2 Sobol analysis).
- Global sensitivity analysis on GADM-0.3 (the Sobol run so far covers
GADM-0.2).
## Reproduce
```bash
@ -350,4 +450,5 @@ python3 -B -m unittest discover -s simulations/gadm02
cd simulations/gadm02 && python3 -B power_channels.py # T03 stage (wealth off)
cd simulations/gadm02 && python3 -B wealth.py # T04: P3 and scenarios
cd simulations/gadm02 && python3 -B organism_grid.py # T05: 2 × 2 × 2 organism grid
cd simulations/gadm02 && python3 -B life_cycle.py # T06: cohorts, L1–L3
```

View file

@ -11,7 +11,7 @@ exploratory: they generate hypotheses and are not established results.
| [InformationOrganismsInGADM.md](InformationOrganismsInGADM.md) | mapping note v0.1 | ASSEMBLY-WP-0003-T03; input for GADM-0.2 (ASSEMBLY-WP-0004) |
| [GADM-CLD.md](GADM-CLD.md) | v0.1 | causal-loop diagram, loops, signed link table (ASSEMBLY-WP-0004-T01/T02) |
| [GADM-0.2.md](GADM-0.2.md) | GADM-0.2 | extensions decision, equations, scenario and sensitivity findings (ASSEMBLY-WP-0004) |
| [GADM-0.3.md](GADM-0.3.md) | in progress | power channels (P1/P2) wealth separated from power (P3), attention recalibration and organism grid (ASSEMBLY-WP-0005-T03–T05) |
| [GADM-0.3.md](GADM-0.3.md) | GADM-0.3 | power channels (P1/P2) wealth separated from power (P3), attention recalibration, organism grid, life-cycle cohorts (ASSEMBLY-WP-0005) |
| [GADM-0.3-Candidates.md](GADM-0.3-Candidates.md) | outline | life-cycle and power extensions, deferred items (ASSEMBLY-WP-0004-T08) |
## Conventions

View file

@ -6,7 +6,8 @@ model version it implements.
| Directory | Model | Entry points |
|-----------|-------|--------------|
| `gadm02/` | GADM-0.2 (`models/GADM-0.2.md`) | `run_scenarios.py`, `sensitivity.py`, `gsa.py`, `test_gadm02.py` |
| `gadm02/gadm03.py` | GADM-0.3: power channels, wealth (`models/GADM-0.3.md`) | `power_channels.py`, `wealth.py`, `organism_grid.py`, `test_gadm03.py` |
| `gadm02/gadm03.py` | GADM-0.3: power channels, wealth, attention (`models/GADM-0.3.md`) | `power_channels.py`, `wealth.py`, `organism_grid.py`, `test_gadm03.py` |
| `gadm02/gadm03c.py` | GADM-0.3 with life-cycle cohorts (`models/GADM-0.3.md` § 5) | `life_cycle.py`, `test_gadm03c.py` |
Python 3.10+, standard library only. Use `python3 -B` after quick edits: a stale
bytecode cache can mask same-size changes made within the same second.

View file

@ -0,0 +1,141 @@
"""GADM-0.3 with life-cycle cohorts (ASSEMBLY-WP-0005-T06).
Extends gadm03 (power channels, wealth, recalibrated attention). Human
capability H and attention headroom A become cohort quantities; everything else
is unchanged and sees population-weighted aggregates:
cohorts: ch (children, 0-19), w (working age, 20-64),
s (seniors, 65-79), d (very old / dependent, 80+)
Population counts N_c evolve by births (b * N_w), ageing (1/20, 1/45, 1/15 per
year) and deaths of the very old (1/8 per year). With b = 1/45 the age
structure is stationary (shares ≈ 23 / 51 / 17 / 9 %).
Intensive cohort quantities follow their own dynamics plus a mixing term when
people age in: dX_c += (inflow_c / N_c) * (X_from - X_c).
Effective agency G stays a single aggregate in this version.
Mentoring (T_g) is an inflow proportional to seniors' capability and
working-age headroom. A first version transferred only max(0, Hs - Hw); since
seniors' capability decays below working-age capability, that term was inert
(L1 showed zero effect) and was replaced.
"""
from __future__ import annotations
import gadm02 as g2
import gadm03 as g3
MODEL_VERSION = "GADM-0.3-cohorts"
TIME_UNIT = g3.TIME_UNIT
COHORTS = ("ch", "w", "s", "d")
AGE_RATE = {"ch": 1 / 20, "w": 1 / 45, "s": 1 / 15}
DEATH_D = 1 / 8
STOCKS = tuple(k for k in g3.STOCKS if k not in ("H", "A")) + (
"Nch", "Nw", "Ns", "Nd", "Hch", "Hw", "Hs", "Hd", "Aw", "As")
INIT = {k: v for k, v in g3.INIT.items() if k not in ("H", "A")}
INIT.update({
# stationary age structure for b = 1/45 (shares of a population of 1)
"Nch": 0.2273, "Nw": 0.5114, "Ns": 0.1705, "Nd": 0.0909,
"Hch": 0.40, "Hw": 0.55, "Hs": 0.55, "Hd": 0.40, # aggregate H ≈ 0.50
"Aw": 0.45, "As": 0.65, # aggregate adult A ≈ 0.50
})
PARAMS = dict(g3.PARAMS)
PARAMS.update({
"birth": 1 / 45, # births per working-age person per year (1/45 = replacement)
"edu": 1.0, # education intensity for children (multiplier)
"tg": 0.05, # intergenerational transfer: seniors' mentoring of working age
"tgc": 0.03, # seniors' mentoring of children
"dHs": 1.5, # capability depreciation multiplier, seniors
"dHd": 3.0, # capability depreciation multiplier, very old
"learn_s": 0.5, # learning multiplier for seniors
"care_load": 0.12, # attention cost of care per unit of care need
"care_sen": 0.3, # share of informal care provided by seniors
"care_relief": 3.0, # relief of informal care per unit of participation claims cp
})
def shares(s: dict) -> dict:
tot = s["Nch"] + s["Nw"] + s["Ns"] + s["Nd"]
return {c: s["N" + c] / tot for c in COHORTS}
def aggregates(s: dict) -> dict:
n = shares(s)
H = sum(n[c] * s["H" + c] for c in COHORTS)
A = (n["w"] * s["Aw"] + n["s"] * s["As"]) / (n["w"] + n["s"])
return {"H": H, "A": A, **{"n_" + c: n[c] for c in COHORTS}}
def derivatives(s: dict, p: dict) -> tuple[dict, dict]:
agg = aggregates(s)
base = {k: v for k, v in s.items() if k in g3.STOCKS}
base["H"], base["A"] = agg["H"], agg["A"]
d3, a = g3.derivatives(base, p)
d = {k: v for k, v in d3.items() if k not in ("H", "A")}
S, B, X, Ko, m = s["S"], a["B"], s["X"], s["Ko"], p["m"]
n = shares(s)
Nch, Nw, Ns, Nd = s["Nch"], s["Nw"], s["Ns"], s["Nd"]
# demography
births = p["birth"] * Nw
flow = {"ch": AGE_RATE["ch"] * Nch, "w": AGE_RATE["w"] * Nw, "s": AGE_RATE["s"] * Ns}
d["Nch"] = births - flow["ch"]
d["Nw"] = flow["ch"] - flow["w"]
d["Ns"] = flow["w"] - flow["s"]
d["Nd"] = flow["s"] - DEATH_D * Nd
# human capability per cohort (GADM-0.2 form, cohort-specific modifiers)
social = p["h0"] * (0.5 * S + 0.5 * B)
desk = p["desk"] * Ko * (1 - m)
Hch, Hw, Hs, Hd = s["Hch"], s["Hw"], s["Hs"], s["Hd"]
d["Hch"] = (p["edu"] * (social + p["hT"] * X) + p["hA"] * s["Aw"] + p["tgc"] * n["s"] / max(n["ch"], 1e-9) * Hs) \
* (1 - Hch) - p["dH"] * Hch
d["Hw"] = (social + p["hA"] * s["Aw"] + p["hT"] * X) * (1 - Hw) - (p["dH"] + desk) * Hw \
+ p["tg"] * n["s"] / max(n["w"], 1e-9) * Hs * (1 - Hw) \
+ flow["ch"] / Nw * (Hch - Hw)
d["Hs"] = p["learn_s"] * (social + p["hA"] * s["As"] + p["hT"] * X) * (1 - Hs) \
- (p["dHs"] * p["dH"] + desk) * Hs + flow["w"] / Ns * (Hw - Hs)
d["Hd"] = -p["dHd"] * p["dH"] * Hd + flow["s"] / Nd * (Hs - Hd)
# attention headroom: extraction (as GADM-0.3) plus informal care load
care_need = 0.5 * n["ch"] + 1.0 * n["d"]
relief = max(0.0, 1 - p["care_relief"] * p["cp"])
load = p["care_load"] * care_need * relief
ext = p["aext"] * p["x_att"] * (0.2 + Ko)
rec = p["arec"] * (0.4 + 0.6 * B)
d["Aw"] = rec * (1 - s["Aw"]) - (ext + load * (1 - p["care_sen"]) / n["w"]) * s["Aw"] \
+ flow["ch"] / Nw * (0.5 - s["Aw"]) # young adults enter with A = 0.5
d["As"] = rec * (1 - s["As"]) - (ext + load * p["care_sen"] / n["s"]) * s["As"] \
+ flow["w"] / Ns * (s["Aw"] - s["As"])
a = {**a, **agg, "care_need": care_need}
return d, a
def simulate(params: dict | None = None, init: dict | None = None,
T: float = 100.0, dt: float = 0.1, record_every: int = 10) -> list[dict]:
p = {**PARAMS, **(params or {})}
s = {**INIT, **(init or {})}
unknown = set(p) - set(PARAMS)
if unknown:
raise KeyError(f"unknown parameters: {sorted(unknown)}")
rows = []
steps = int(round(T / dt))
for i in range(steps + 1):
d, a = derivatives(s, p)
if i % record_every == 0:
row = {"t": round(i * dt, 6), **s, "P": g3.total_p(s),
**{k: a[k] for k in ("H", "A", "n_ch", "n_w", "n_s", "n_d", "care_need",
"Ystar", "B", "V", "Vsel")}}
row["VFAC"] = g2.vfac(row)
rows.append(row)
if i < steps:
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 STOCKS}
return rows

View file

@ -0,0 +1,80 @@
"""Life-cycle hypotheses L1-L3 for GADM-0.3 with cohorts (gadm03c).
L1: strong intergenerational transfer T_g lets an ageing society keep H.
L2: care demand competes with attention; without recognized care participation
(C_p), attention headroom falls fastest in the working-age cohort.
L3: children's capability formation reaches working-age capability with a lag
of 15-20 years.
Usage: python3 -B simulations/gadm02/life_cycle.py
"""
from __future__ import annotations
import sys
from pathlib import Path
sys.dont_write_bytecode = True
import gadm03c as c # noqa: E402
from scenarios import load_all # noqa: E402
OUT = Path(__file__).resolve().parent / "results"
STABLE, AGEING = 1 / 45, 0.75 / 45
def run(params: dict, base: dict) -> list[dict]:
return c.simulate({**base["params"], **params}, base["init"])
def main() -> None:
OUT.mkdir(exist_ok=True)
sc = load_all()["baseline"]
lines = [f"# {c.MODEL_VERSION}: life-cycle hypotheses", "",
"Generated by `simulations/gadm02/life_cycle.py`. Baseline background,",
"t = 100 years. Ageing demography: births at 75 % of replacement.", ""]
lines += ["## L1: intergenerational transfer in an ageing society", "",
"| Demography | T_g (tg) | seniors + very old (share, t=100) | H (t=0) | H (t=100) | ΔH |",
"|---|---|---|---|---|---|"]
for demo, b in (("stable", STABLE), ("ageing", AGEING)):
for tg in (0.0, 0.05, 0.15):
r = run({"birth": b, "tg": tg}, sc)
old = r[-1]["n_s"] + r[-1]["n_d"]
lines.append(f"| {demo} | {tg:.2f} | {old:.2f} | {r[0]['H']:.3f} | {r[-1]['H']:.3f} | "
f"{r[-1]['H'] - r[0]['H']:+.3f} |")
lines += ["", "## L2: care load and attention", "",
"Levels at t = 100 are compared across settings (not against t = 0, because",
"initial cohort attention is not at its own equilibrium).", "",
"| Demography | care_sen (seniors' care share) | cp | A working age | A seniors | care load per working-age person | per senior |",
"|---|---|---|---|---|---|---|"]
for demo, b in (("stable", STABLE), ("ageing", AGEING)):
for cs in (0.1, 0.3):
for cp in (0.0, 0.15):
prm = {"birth": b, "cp": cp, "care_sen": cs}
r = run(prm, sc)[-1]
pp = {**c.PARAMS, **sc["params"], **prm}
load = pp["care_load"] * r["care_need"] * max(0.0, 1 - pp["care_relief"] * cp)
lines.append(f"| {demo} | {cs:.1f} | {cp:.2f} | {r['Aw']:.3f} | {r['As']:.3f} | "
f"{load * (1 - cs) / r['n_w']:.4f} | {load * cs / r['n_s']:.4f} |")
lines += ["", "## L3: lag from education to working-age capability", "",
"Run difference: education intensity 1.5 vs. 1.0, everything else equal.", "",
"| t | ΔH children | ΔH working age | ΔH aggregate |", "|---|---|---|---|"]
lo, hi = run({"edu": 1.0}, sc), run({"edu": 1.5}, sc)
diffs = [(a["t"], b["Hch"] - a["Hch"], b["Hw"] - a["Hw"], b["H"] - a["H"]) for a, b in zip(lo, hi)]
for t, dc, dw, dh in diffs:
if t in (0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100):
lines.append(f"| {t:.0f} | {dc:+.3f} | {dw:+.3f} | {dh:+.3f} |")
final_w, final_c = diffs[-1][2], diffs[-1][1]
t_w = next(t for t, _dc, dw, _dh in diffs if dw >= 0.5 * final_w)
t_c = next(t for t, dc, _dw, _dh in diffs if dc >= 0.5 * final_c)
lines += ["", f"Half of the final effect is reached after {t_c:.0f} years for children and "
f"{t_w:.0f} years for working-age capability.", ""]
(OUT / "life_cycle.md").write_text("\n".join(lines))
print("\n".join(lines))
if __name__ == "__main__":
main()

View file

@ -0,0 +1,51 @@
# GADM-0.3-cohorts: life-cycle hypotheses
Generated by `simulations/gadm02/life_cycle.py`. Baseline background,
t = 100 years. Ageing demography: births at 75 % of replacement.
## L1: intergenerational transfer in an ageing society
| Demography | T_g (tg) | seniors + very old (share, t=100) | H (t=0) | H (t=100) | ΔH |
|---|---|---|---|---|---|
| stable | 0.00 | 0.26 | 0.502 | 0.459 | -0.043 |
| stable | 0.05 | 0.26 | 0.502 | 0.470 | -0.032 |
| stable | 0.15 | 0.26 | 0.502 | 0.491 | -0.011 |
| ageing | 0.00 | 0.29 | 0.502 | 0.450 | -0.053 |
| ageing | 0.05 | 0.29 | 0.502 | 0.462 | -0.040 |
| ageing | 0.15 | 0.29 | 0.502 | 0.485 | -0.018 |
## L2: care load and attention
Levels at t = 100 are compared across settings (not against t = 0, because
initial cohort attention is not at its own equilibrium).
| Demography | care_sen (seniors' care share) | cp | A working age | A seniors | care load per working-age person | per senior |
|---|---|---|---|---|---|---|
| stable | 0.1 | 0.00 | 0.399 | 0.438 | 0.0432 | 0.0144 |
| stable | 0.1 | 0.15 | 0.441 | 0.465 | 0.0238 | 0.0079 |
| stable | 0.3 | 0.00 | 0.417 | 0.395 | 0.0336 | 0.0432 |
| stable | 0.3 | 0.15 | 0.452 | 0.439 | 0.0185 | 0.0238 |
| ageing | 0.1 | 0.00 | 0.402 | 0.443 | 0.0407 | 0.0128 |
| ageing | 0.1 | 0.15 | 0.443 | 0.468 | 0.0224 | 0.0070 |
| ageing | 0.3 | 0.00 | 0.420 | 0.403 | 0.0317 | 0.0383 |
| ageing | 0.3 | 0.15 | 0.454 | 0.444 | 0.0174 | 0.0210 |
## L3: lag from education to working-age capability
Run difference: education intensity 1.5 vs. 1.0, everything else equal.
| t | ΔH children | ΔH working age | ΔH aggregate |
|---|---|---|---|
| 0 | +0.000 | +0.000 | +0.000 |
| 5 | +0.053 | +0.003 | +0.013 |
| 10 | +0.067 | +0.006 | +0.018 |
| 15 | +0.069 | +0.008 | +0.020 |
| 20 | +0.069 | +0.008 | +0.020 |
| 25 | +0.068 | +0.009 | +0.020 |
| 30 | +0.068 | +0.009 | +0.020 |
| 40 | +0.067 | +0.009 | +0.020 |
| 50 | +0.067 | +0.009 | +0.020 |
| 75 | +0.067 | +0.010 | +0.021 |
| 100 | +0.067 | +0.010 | +0.021 |
Half of the final effect is reached after 3 years for children and 9 years for working-age capability.

View file

@ -0,0 +1,44 @@
"""Sanity tests for GADM-0.3 with cohorts.
Usage: python3 -B -m unittest discover -s simulations/gadm02
"""
import unittest
import gadm03c as c
from scenarios import load_all
class TestCohorts(unittest.TestCase):
def test_bounded_and_shares_sum_to_one(self):
for name, sc in load_all().items():
for row in c.simulate(sc["params"], sc["init"]):
for k in c.STOCKS:
if not k.startswith("N"):
self.assertGreaterEqual(row[k], 0.0, (name, k))
self.assertLessEqual(row[k], 1.0, (name, k))
self.assertAlmostEqual(row["n_ch"] + row["n_w"] + row["n_s"] + row["n_d"], 1.0)
def test_replacement_fertility_is_stationary(self):
r = c.simulate()
for k in ("n_ch", "n_w", "n_s", "n_d"):
self.assertAlmostEqual(r[0][k], r[-1][k], places=3, msg=k)
def test_low_fertility_ages_the_population(self):
r = c.simulate({"birth": 0.75 / 45})[-1]
s = c.simulate()[-1]
self.assertGreater(r["n_s"] + r["n_d"], s["n_s"] + s["n_d"])
def test_mentoring_raises_capability(self):
lo = c.simulate({"tg": 0.0})[-1]["H"]
hi = c.simulate({"tg": 0.15})[-1]["H"]
self.assertGreater(hi, lo)
def test_care_relief_raises_working_age_attention(self):
lo = c.simulate({"cp": 0.0})[-1]["Aw"]
hi = c.simulate({"cp": 0.15})[-1]["Aw"]
self.assertGreater(hi, lo)
if __name__ == "__main__":
unittest.main()

View file

@ -4,7 +4,7 @@ type: workplan
title: "GADM-0.3: global sensitivity, power channels, cohorts"
domain: communication
repo: assembly-economics
status: active
status: finished
flavor: residual
origin: residual
origin_ref: ASSEMBLY-WP-0004
@ -89,10 +89,32 @@ organism scenario grid (lineage × membrane × attention regime).
```task
id: ASSEMBLY-WP-0005-T06
status: todo
status: done
priority: low
state_hub_task_id: "2b749127-9f41-5bff-9a56-19ccd8fe9dd6"
```
Implement `GADM-0.3-Candidates.md` § 1: four cohorts, intergenerational
transfer, and care demand on attention. Test hypotheses L1–L3.
## Outcome
All tasks are done. Results are in `models/GADM-0.3.md` and
`models/GADM-0.2.md` § 5.1.
- T01: one period = one year; global sensitivity analysis. The model is
nearly additive. The "reuse as a bundle" reading was refuted, and organism
governance levers were confirmed as dominant.
- T02: literature verified; AI-growth prior art added; novelty claim 2
narrowed.
- T03: six power channels. P1 is mostly unsupported, except lineage
hysteresis; P2 is supported.
- T04: wealth separated from power. P3 is supported and robust.
- T05: attention recalibrated against time-use data. In the 2 × 2 × 2 grid,
lineage ownership is the strongest organism lever.
- T06: life-cycle cohorts. L1 is supported (after fixing an inert mentoring
term), L2 is conditional, and L3 is not supported (a missing durable-capability
mechanism).
Residual: ASSEMBLY-WP-0006 (GADM-0.4, proposed) carries the open items in
`GADM-0.3.md` § 6.

View file

@ -0,0 +1,91 @@
---
id: ASSEMBLY-WP-0006
type: workplan
title: "GADM-0.4: durable capability, cohort agency, estimated parameters"
domain: communication
repo: assembly-economics
status: proposed
flavor: residual
origin: residual
origin_ref: ASSEMBLY-WP-0005
depends_on: [ASSEMBLY-WP-0005]
owner: claude-code
topic_slug: coulomb-social
created: "2026-10-12"
updated: "2026-10-12"
---
# GADM-0.4: durable capability, cohort agency, estimated parameters
Residual of ASSEMBLY-WP-0005: the open items in `models/GADM-0.3.md` § 6, plus
the GADM-0.1 § 26 plan for GADM-0.4. Not to be started until it is promoted
to `ready`.
## Split human capability into durable and current components
```task
id: ASSEMBLY-WP-0006-T01
status: todo
priority: high
```
L3 failed because H has no memory of childhood. Add a slowly depreciating,
education-formed component next to the current one, then re-test L3.
## Ground key parameters
```task
id: ASSEMBLY-WP-0006-T02
status: todo
priority: high
```
Replace the assumed values of organism depreciation `dO` (the top Sobol
driver), channel self-reinforcement r_k and wealth conversion k_w with
literature- or data-based ranges. Re-run the affected readings.
## Global sensitivity on GADM-0.3
```task
id: ASSEMBLY-WP-0006-T03
status: todo
priority: medium
```
Extend `gsa.py` to the GADM-0.3 models (channels, wealth, cohorts). Check
whether the near-additivity of GADM-0.2 survives the superlinear channel
dynamics.
## Equilibrium initialisation
```task
id: ASSEMBLY-WP-0006-T04
status: todo
priority: medium
```
Initialise W and the cohort attention stocks at their own equilibria, to
remove the initial-condition confounds noted in `GADM-0.3.md` §§ 3.4 and 5.3.
## Agency per cohort
```task
id: ASSEMBLY-WP-0006-T05
status: todo
priority: low
```
Give G a cohort structure (restartability and exit options differ strongly
by age).
## Sectors and rival goods
```task
id: ASSEMBLY-WP-0006-T06
status: todo
priority: low
```
GADM-0.1 § 26 plan for GADM-0.4: multiple sectors, rival versus non-rival
goods, ecological resource classes, institutional selection mechanisms.
Scope this into its own workplan before implementing it.