Simulating the AI Structural Shift: Measuring the Human Impact with PyCausalSim

A fifteen-year forecast, encoded as a temporal causal model and run 4,000 times. One policy lever turns out to be worth 2.8 of another, and the ranking contradicts the essay it came from.
A technical follow-up to “A Note from the Future: How AI Changed Lives and the Outcome.”
Code and Reproduction
The model is open. pycausalsim.futures and the full post-labor implementation ship in the repository under MIT, so every figure and every number in this piece regenerates from a fixed seed on any machine:
pip install git+https://github.com/Bodhi8/pycausalsim.git python examples/postlabor_futures.py
A regression test asserts the example reproduces the published figures exactly, so a change to the engine that silently alters results fails rather than passing quietly.
Annual subscribers receive the research layer rather than the code: the derivation of each parameter prior with its source anchoring, the figure scripts that produced the charts above, a scenario workbook for running variants without writing Python, and the dated claim set with its resolution calendar and annual scoring.
Figures were produced from 4,000 Monte Carlo draws over the parameter priors. The exogenous cost decay samples at 0.52 log-decades per year with a standard deviation of 0.10, deliberately slower than the observed tenfold annual decline, on the grounds that saturation is likelier than continuation. Anchoring values for 2026 come from the sources cited in the original essay.
PyCausalSim: github.com/Bodhi8/pycausalsim
Why a Forecast Should Be Executable
Prose forecasting has a structural problem. It presents a sequence of locally plausible claims, and the reader has no way to determine which ones carry the argument. Neither does the author. Rhetoric conceals the dependency structure, so a near-mechanical claim about housing and a speculative claim about wellbeing appear identical on the page.
A causal model removes that concealment by construction. Each claim becomes an edge or a coefficient. Each coefficient takes a prior. Each conclusion becomes a distribution rather than a sentence, and the width of that distribution reports how much was actually known. Most usefully, holding one variable fixed while varying another is the only reliable way to establish whether a policy lever matters or merely fits a persuasive narrative.
The forecast in the preceding article was therefore encoded as a temporal structural causal model, sampled across 4,000 parameter draws, and run under three policy scenarios to 2041. Two of the original claims survive intact. One strengthens substantially. One has the emphasis wrong, and the model identifies which sentence is responsible.
The Graph
The model has a single exogenous driver. Everything else is downstream.
The cost of cognition falls at a sampled rate near threefold per year, discounted from the observed tenfold on the grounds that saturation is likelier than continuation. That drives automation depth through a saturating logistic, which is the only mechanically determined link in the graph.
Automation depth then splits four ways:
- Entry-level hiring falls with automation depth and rises with deliberate apprenticeship spending. This is the severed ladder.
- Verification demand rises with automation depth, since more machine output means more output requiring inspection.
- Cognitive prices collapse toward zero while bottleneck prices for land, energy, and care rise. The price index is the expenditure-weighted blend, and as the cognitive weight vanishes, the index converges on the bottleneck alone.
- Capital share drifts upward, offset only by deliberate ownership transfer.
The consequential structure appears downstream of the first branch. Senior stock, defined as the population capable of verifying machine output, accumulates from entry-level cohorts lagged ten years, net of attrition. It is the only state variable carrying memory, and that memory produces most of the model’s interesting behavior.
# Senior judgment is produced by junior hiring, ten years earlier S[t] = S[t-1] * (1 - attrition) + conversion * J[t-10] # Verification is the weak link, so output is capped by it gap = demand[t] / capacity[t] Y[t] = potential[t] / (1 + 2.2 * max(0, gap - 1))
Wellbeing is modeled on Jahoda’s latent deprivation structure rather than on income. For the population share outside formal employment, wellbeing combines material adequacy (sourced from the income floor plus any cooperative yield) with latent function supply (sourced from institutions). The weight on latent functions samples around 0.62, reflecting the finding that people out of the labor force report status indistinguishable from the employed, while the unemployed report substantially less.
material = sigmoid(4.0 * (floor_income / cpi - 0.72)) latent = institutions * (0.55 + 0.45 * institutions) W_out = (1 - w_latent) * material + w_latent * latent W = U * W_out + (1 - U) * W_employed
One modeling decision carries more weight than any coefficient. Apprenticeship is treated as an input to the senior stock and also as an institution in its own right, on the grounds that it supplies time structure, social contact, status, collective purpose, and effortful activity against real resistance. Apprenticeship spending therefore enters the latent function term as well as the labor supply term. The decision is defensible on the psychological evidence, and it changes the ranking of the policy levers. That is precisely the kind of dependency that stays invisible in prose.
Expressing the Model in PyCausalSim
PyCausalSim was designed for causal discovery on observational data: learn a graph, then simulate interventions within the support of the observed data. Forecasting inverts both halves. The graph is specified rather than discovered, and every intervention of interest lies far outside observed support. The simulation and validation machinery still applies. The discovery layer does not.
from pycausalsim.models import StructuralCausalModel
from pycausalsim import CausalSimulator
scm = StructuralCausalModel()
scm.add_equation("automation", f_automation, parents=["token_price"])
scm.add_equation("junior", f_junior, parents=["automation", "R"])
scm.add_equation("senior", f_senior, parents=["junior:lag10", "senior:lag1"])
scm.add_equation("verify_gap", f_gap, parents=["automation", "senior"])
scm.add_equation("cpi", f_cpi, parents=["automation", "O"])
scm.add_equation("wellbeing", f_wellbeing, parents=["cpi", "F", "I", "R", "verify_gap"])
sim = CausalSimulator.from_scm(scm, target="wellbeing", horizon=16)
drift = sim.simulate_scenario({"F": 0.25, "I": 0.10, "R": 0.05, "O": 0.05})
transfers = sim.simulate_scenario({"F": ramp(2032, 0.85), "I": 0.15})
full = sim.simulate_scenario({"F": ramp(2031, 0.60), "I": ramp(2028, 0.78),
"R": ramp(2027, 0.72), "O": ramp(2028, 0.52)})
sim.rank_drivers(at_year=2041)Three of those calls do not exist yet. from_scm, simulate_scenario, and the lag syntax inside parents are what this exercise established the library needs. The final section specifies them.
Result One: The Notch Is More Severe Than Forecast
The preceding essay described the expertise notch as a forty-year problem arriving around 2035. The model confirms the timing and indicates the severity was understated.

Verification demand reaches 236 by 2041 against a capacity of 143, a shortfall of 65 percent. Capacity peaks near 2038 and then declines, which is when the depressed cohorts arrive at the point in the pipeline where the senior stock should be replenishing. Senior stock in 2041 sits at 94 percent of its 2026 level under Drift, and 99 percent with funded apprenticeship. The difference between those two figures is worth 7.6 percent of output.
One result was not anticipated by the essay. The gap is still widening at the end of the horizon in every scenario, including full apprenticeship funding commenced in 2027. Nothing in the model reverses it by 2041, because a ten-year production lag inside a fifteen-year window leaves insufficient time. Closing the notch by 2041 required intervention beginning before the forecast period opens.
Result Two: Transfers Close Roughly a Quarter of the Gap
Three scenarios were run. Drift holds current policy. Transfers Only introduces a substantial income floor from 2032 and changes nothing else. Ownership and Institutions funds civic institutions from 2028, apprenticeship from 2027, and cooperative ownership transfer from 2028, alongside a smaller income floor.

Drift lands at 0.41, with a 90 percent interval from 0.32 to 0.51. Transfers Only reaches 0.49, exceeding Drift in 93 percent of draws. Ownership and Institutions reaches 0.70, exceeding Drift in 100 percent of draws and with a visibly narrower band, since institutions reduce variance as well as raising the mean.
Transfers alone recover 27 percent of the distance between doing nothing and the full package. That figure is the quantitative form of the essay’s claim that societies handling the transition badly would send checks and consider the problem solved. The model does not find transfers useless. It finds that they purchase roughly a quarter of what is available, and that the remaining three-quarters cannot be purchased with money.
Two secondary outputs merit attention. Capital share reaches 0.55 under Drift against 0.31 with ownership transfer. The legitimacy index, tracking whether the distribution is socially defensible, reaches 0.49 under Drift against 0.97. Legitimacy shows the widest spread between scenarios of any variable in the model, indicating that the political failure mode is more policy-sensitive than the material one.
Result Three: The Ranking, and a Correction
Raising each lever to matched intensity, one at a time, holding everything else at Drift, gives the forecasting equivalent of rank_drivers().

- nstitution funding delivers +0.136. This looks like heavy investment in community centers, local civic boards, and public works projects that provide people with social structure, purpose, and status outside of traditional employment.
- Apprenticeship investment delivers +0.065. This involves policies like state-subsidized mentor hours, public guilds, or direct financial incentives for companies to absorb and train junior workers who would otherwise be automated out.
- Ownership transfer delivers +0.053. In practice, this means establishing citizen wealth funds, expanding employee stock ownership programs, or mandating cooperative equity models to distribute the dividends of automation.
- The income floor delivers +0.049. This represents direct financial interventions like a universal basic income or a negative income tax.
Institution funding outranks the income floor by 2.8 to 1. The first result confirms the essay’s central claim, and confirms it more strongly than the essay argued it. The last result corrects the essay.
Ownership transfer ranks third. This runs against the emphasis of the preceding piece and against a position argued publicly since 2016. The cause is not that ownership fails to matter. It compresses capital share from 0.55 to 0.31 and nearly doubles the legitimacy index, and both effects are large. But its influence on the variable the essay identified as the actual outcome (whether a 24-year-old has a life worth living) runs almost entirely through the income channel, and income is the weaker of the two channels feeding wellbeing. Ownership resolves the distribution problem. It does not by itself resolve the five functions problem.
That correction would not have emerged from more careful writing. Apprenticeship investment outranking ownership transfer follows directly from the decision to treat apprenticeship as an institution, an assumption invisible in an essay and explicit in a model. Rejecting that assumption flips second and third place, and a reader who disagrees now knows exactly which line to argue with.
What the Model Does Not Know
Stated directly, since a model that suppresses its weaknesses is a rhetorical device rather than an instrument:
- The wellbeing index is a construct, not a measured quantity. Built from the Jahoda literature, its absolute level carries no meaning. Only differences between scenarios are interpretable, and only if the functional form is approximately correct.
- The graph is specified, not discovered. Every edge reflects a judgment about the economics. The Monte Carlo quantifies uncertainty over coefficients, not over structure, and structural uncertainty is almost certainly larger.
- The exogenous driver is a single scalar. Capability progress is not one number declining smoothly, and a discontinuity anywhere in the horizon breaks the saturating logistic.
- There is no geography and no agent heterogeneity. The essay argued that place matters more than occupation. This model cannot represent place at all, which is its largest omission.
- The ten-year lag rests on a single anchor. It derives from the observed structure of professional apprenticeship rather than from a fitted parameter, and every result concerning the notch scales with it.
Turning PyCausalSim into a Futurist Engine
Building this model exposed the distance between what the library does and what forecasting requires. PyCausalSim is retrodictive by design. It learns a graph from existing data and estimates interventions within that data’s support. Futures work requires capabilities the current architecture lacks, none of them trivial.
1. Time as a First-Class Citizen
Causal graphs in the library are cross-sectional. Futures are trajectories, and the consequential dynamics live in lags and accumulation. The severed ladder is only interesting because a decade separates an intervention from its consequence.
The fix is a TemporalSCM that unrolls a graph across a horizon, with lag specification in the parent declaration and state variables carrying memory. This is established ground in dynamic Bayesian networks, and the unrolled graph remains acyclic, so existing identification and simulation machinery continues to apply.
from pycausalsim.futures import TemporalSCM
scm = TemporalSCM(horizon=range(2026, 2042), step="year")
scm.state("senior_stock", init=lambda p: p.conversion / p.attrition * 100)
scm.add_equation("senior_stock", f_senior,
parents=["junior:lag(10)", "senior_stock:lag(1)"])2. Extrapolation with Declared Mechanism
Every forecast intervention is out of support. No observation exists of cognition priced at a thousandth of current rates, so a fitted response surface has nothing to contribute. Fitted models extrapolate badly and silently, which is the worst available combination.
The fix is to require an explicit MechanismPrior on any edge that will be driven outside observed range: a declared functional form, a validity range, and specified behavior at the boundary. The engine then refuses to extrapolate through an undeclared edge, or flags the result as unsupported. A futures engine should be loud about which conclusions rest on observed data and which rest on assumed physics.
scm.mechanism("automation ~ token_price",
form="logistic", saturates_at=1.0,
valid_range=(0.001, 100.0), outside="flag")3. Structural Interventions, Not Only Value Interventions
This is the deepest gap. Pearl’s do() operator sets a variable to a value. It does not delete an edge. Yet the most consequential futures questions are structural. The severed ladder is the removal of the edge from junior production to senior expertise, not a change in that edge's input. Automation does not lower the value of apprenticeship. It severs the mechanism by which apprenticeship previously occurred as a free byproduct.
A futurist engine needs interventions that add, remove, and rewire edges, and it needs to represent structure change as itself caused by value change. Cheap cognition causes the edge deletion. No current causal library expresses that relationship.
from pycausalsim.futures import StructuralIntervention as SI
# The byproduct channel dies when automation depth crosses a threshold
scm.structural_rule(
when="automation > 0.55",
apply=SI.remove_edge("junior_production", "senior_expertise"),
note="Training stops being a free byproduct of junior output")4. A Scenario Language
Scenarios should be declarative and legible to people who do not write Python, since the constituency that should be arguing with a forecast is largely non-technical. A scenario is a named bundle of timed interventions, and it should be comparable, composable, and diffable against other scenarios.
from pycausalsim.futures import Scenario
kc_coop = Scenario("Ownership and institutions")
kc_coop.at(2027).set("apprenticeship", ramp_to=0.72, over=4)
kc_coop.at(2028).set("institutions", ramp_to=0.78, over=6)
kc_coop.at(2028).set("ownership", ramp_to=0.52, over=7)
kc_coop.at(2031).set("income_floor", ramp_to=0.60, over=3)
results = scm.compare([drift, transfers_only, kc_coop], draws=4000)
results.rank_drivers(at=2041)
results.diff(kc_coop, drift).plot()5. The Falsifier
Futurism has no accountability mechanism. Predictions are issued, events occur, and nothing is scored. An engine that emits dated, checkable claims with confidence intervals attached, and stores them for later scoring, does something no essay can do.
This is the component to build first, because it is what makes the rest credible. Running the model emits claims of the same form as the eight in the original forecast, with probabilities attached and a data source named for each.
claims = results.falsifiable_claims(threshold=0.70)
# FalsifiableClaim(
# statement="entry-level gap in exposed occupations exceeds 25%",
# resolve_by=2029, p=0.81,
# source="Stanford Digital Economy Lab payroll series",
# scenario="Drift")
claims.export("claims_2026.json")
results.score(against="claims_2024.json") # How did last year's model do?6. Backtesting
Fit the structural model on data through 2018, run it forward to 2026, and score against what actually occurred. A futures engine unable to retrodict the preceding eight years has no standing to forecast the next fifteen, and its backtest score belongs next to every forecast it produces.
bt = scm.backtest(fit_through=2018, evaluate=(2019, 2026),
anchors=["entry_level_gap", "token_price", "capital_share"])
print(bt.summary()) # Per-anchor error, calibration of the intervals7. The Agent Layer
PyCausalSim already ships an agents/ module. The aggregate model presented here cannot distinguish between the two 24-year-olds described in the original essay, since it tracks population means only, and the essay's entire argument was that two people with identical material conditions can have non-comparable lives. An agent layer with heterogeneous institution access, geography, and cohort would recover that distinction and allow the model to report variance across people rather than the mean alone.
What This Is For
The value of an executable forecast does not lie in its being correct. It will not be. The value lies in its being arguable at the level of individual assumptions, which prose forecasting never permits.
A reader who rejects the 2.8 to 1 ratio between institution funding and the income floor should attack the 0.62 weight on latent functions in the wellbeing equation, and can consult the Jahoda meta-analyses and argue for 0.4. A reader who considers the notch overstated should attack the ten-year lag. A reader who rejects the whole structure has the published graph and can rewire it and produce a different answer.
That is a more productive public argument than the current one, which consists of confident essays aimed at each other. The necessary tooling exists in fragments across causal inference, systems dynamics, and agent-based modeling, and nobody has assembled those fragments into something a policy analyst or a city government could run. That assembly is the roadmap for PyCausalSim.
Code and Reproduction
The complete reference implementation is available to annual subscribers: structural equations, parameter priors, scenario definitions, the driver ranking routine, and the figure scripts. Every number reported in this piece regenerates from a fixed seed, and editing the structural equations updates the figures on the next run. The bundle includes a README documenting the graph, the four policy levers, the modification points, and the assumptions most worth testing.
Figures were produced from 4,000 Monte Carlo draws over the parameter priors. The exogenous cost decay samples at 0.52 log-decades per year with a standard deviation of 0.10, deliberately slower than the observed tenfold annual decline, on the grounds that saturation is likelier than continuation. Anchoring values for 2026 come from the sources cited in the original essay.
PyCausalSim: github.com/Bodhi8/pycausalsim
About the Author

Brian Curry is a Kansas City-based Machine Learning & AI Strategist, Marketing Economist, and Applied Researcher. He drives Vector1, an independent research studio working at the frontiers of cognitive AI, causal inference, marketing economics, and knowledge engineering to build simulation-driven intelligence systems.
Across more than twenty years, Brian has led advanced data science and analytics initiatives at enterprises ranging from $4B to $125B in revenue, including Koch Industries, Tractor Supply, Vail Resorts, Hallmark, Garmin, and AT&T. His work systematically applies economic thinking and causal inference to connect marketing investment to structural outcomes, operational decisions to economic value, and AI adoption to permanent competitive advantage.
He is also the founder of KC AI Lab, a 1,500-member AI/ML education community in the Midwest.
Key Research & Open-Source Projects
GitHub: @Bodhi8
Substack: https://brianjamescurry.substack.com/
Causal Inference & Marketing Economics
- PyCausalSim: A Python framework for simulation-driven causal discovery and evaluation, mapping counterfactual scenarios to isolate true structural drivers.
- Papilon: A complex-system simulation and optimization library optimized for Media Mix Modeling (MMM) and adaptive architectures.
- Daedalus: A causal analytics framework designed for money-flow mapping and macro-economic tracking.
Algorithmic Engineering & Applied Forecasting
- Regimecast: Applied research and tooling for time-series regime detection, structural breaks, and economic forecasting.
- CarryNet: Open-source research and financial modeling focused on commodity carry trade analysis.
- Foodmesh-ml: A machine learning, optimization, and simulation framework engineered for modeling distributed food systems.
Cognitive AI & Semantic Knowledge Architecture
- Memory-Node Encapsulation (MNE): A cognitive AI architecture and novel data structure for artificial episodic memory (NeoCortex-M).
- The Autonomy Economy: A macroeconomic framework projecting the dual impacts of massive productivity growth and extreme structural price deflation in an AI-automated world.
- MeaningFlow: A semantic intelligence framework focused on content modeling, embeddings, clustering, and automated coverage gap analysis.
Contact: brian@vector1.ai | GitHub | Substack
This article may be shared with attribution under Creative Commons Attribution 4.0 International (CC BY 4.0).


