Better To Best Research Hub
Compassionism Framework Simulation v4.4
All five architectures · CCO · PTF · PTH · SZH · CIP · BLEI-calibrated
Loading illustrative reference run…Run Simulation.
CCO: OffPTF: OffPTH: OffSZH: OffCIP: Off
Run configuration
Economic Outcomes
Wealth Poverty Rate
Gini Coefficient
Median Wealth
System Stability
Temporal Stability · BLEI Framework↗ paper
Median BLEI Score
Agents at Top BLEI Tier (730+ days)
Avg Extractive Drain (EDC)
BLEI Poverty (< 30 days)
Economic Trajectory
Poverty rate — scenario vs baseline
Dashed = US welfare baseline trajectory (same years; recessions apply to baseline only when your scenario has them enabled — see Cumulative Bug Fixes)
Gini coefficient over time
Wealth distribution — p10 / median / p90
Dashed lines = bottom/top deciles · Filled band = median trajectory · Inequality envelope
BU velocity & conversion activity
BLEI Temporal Stability
Median BLEI score — days of basic living covered
Threshold 30d · Stable 120d · Secure 365d · Flourishing/Comfortable 730d
BLEI tier distribution — final year
Six-tier welfare classification (Johnson & Claude, 2026)

System comparison — final-year results  Baseline/CCO-only top tier = Comfortable; CCO+PTF = Flourishing

Top BLEI tier label: 'Comfortable' for baseline/CCO-only (730+ days aspirational without PTF/PTH cost reduction); 'Flourishing' when CCO+PTF active. Both thresholds = 730 days — label reflects realistic attainability. See BLEI paper for full tier definitions.

ConfigurationPoverty elim.Median wealthGiniMedian BLEIAvg EDCStability
Run the simulation to see results.
📋 Assumptions, ODD Protocol & Known Limitations v4.4 — click to expand 📐 ODD Protocol — Grimm et al. (2010) standard ABM description
Overview: Purpose & Entities

Purpose: Explore Compassionism parameter space; identify conditions under which poverty targets are met; provide comparable scenario analyses for policy discussion. Not a forecasting model. Entities: Households (agents) characterised by economic state. Scales: 100–2000 agents; 5–30 annual time steps. Each agent represents one adult household unit.

Overview: State Variables

Per agent: wealth (USD), wage (SIU), octave (skill tier 0–maxOct), quality (1–9×), automationRisk ∈ [0.2,1.0], inCCO/inPTF/inPTH (participation flags), buBalance, acreEquity. Aggregate observables: poverty rate, Gini, BLEI tier distribution, EDC, stability index.

Design Concepts: Emergence & Adaptation

Emergence: Poverty, inequality, and BLEI tier distributions emerge from agent-level rules — not directly imposed. Adaptation: Octave advancement gated by FBS (Mullainathan & Shafir bandwidth constraint). PTF adoption via economic distress and social diffusion (Bass 1969 model). No explicit utility maximisation — behavioural rules only.

Design Concepts: Interaction & Stochasticity

Interaction: Indirect market-mediated only — no direct agent-to-agent interaction. Cooperative effects via PTF/SZH zone parameters. Stochasticity: Seeded PRNG (mulberry32); wage variance ±10%; recession events 10% annual probability (beta(5,2) severity); BU spend rates 60–90%; octave advancement (FBS-gated probability). Same seed + params → identical run.

Details: Initialization

Agent wealth: lognormal(10.5,1.2) → median ~$36K (Fed SCF 2022). Wage: lognormal(3.5,0.5) → median ~33 SIU. Octave: beta(2,5)×maxOct. Quality: lognormal(log(maxMult×0.5),0.4). automationRisk: 47%/53% bimodal mixture, Beta(6,1) high-risk / Beta(1,6) low-risk (v4.3; was uniform[0.2,1.0] through v4.2 — see Cumulative Bug Fixes). λ (FBS capability coefficient, v4.0): uniform[0.0001654,0.0013233] per agent (v4.4: rescaled ÷6.0456 from the pre-v4.4 [0.001,0.008] — see Cumulative Bug Fixes). Participation flags assigned at initialization probabilities. Baseline, CCO-only, and Main are instantiated from one shared canonical latent population (v4.2) — same n individuals, three policy configs — with no initial-wealth adjustment applied to any of them as of v4.4 (previously baseline agents received an undocumented-provenance ×0.85 wealth haircut; removed — see Cumulative Bug Fixes).

Details: Submodels

Annual update (runYear): wage growth with diminishing returns → living cost subtraction (SIM_COST_SCALE) → CCO conversion income at a rate capped by octave-tier capacity → FBS-gated octave advancement check (v4.0) → PTH Acre Equity appreciation plus a payment→equity contribution (v4.0) → PTF adoption check (innovation + distress + Bass imitation, v4.0) → wealth floor clamp. BLEI = (liquid + γ·wage·SIU_TO_USD + buFood) / dailyCost (v4.0: wage converted to USD before summing — see Empirical Calibration below). Gini (v4.0): computed on EDC-adjusted net wealth, W_nominal − EDC×Y×12. Recession: beta(5,2) incomeMultiplier ∈ [0.70,0.95], NBER-calibrated (nber.org) — mode 0.90 (10% loss), mean ≈0.88 (~12% loss).

🔧 Cumulative Bug Fixes (v3.1 → v4.4)
Wage/income scale unification — BLEI, FBS, and Gini now share the main loop's real-dollar anchor (v4.4)

v4.0 fixed wage/USD unit mixing inside BLEI, FBS, and Gini using SIU_TO_USD ≈16.63 — a cost-side-derived approximation invented because no real wage-side dollar anchor existed yet. v4.3 later added WAGE_TO_USD ≈100.52, a genuine Census/BLS-sourced anchor, but scoped it to the main wealth loop only. The result: the same agent's wage resolved to two different real-dollar figures depending which formula asked it — at the median wage, ~$3,518/mo for wealth accumulation versus ~$582/mo for welfare measurement, a ~6× divergence (external audit finding). CFG.SIU_TO_USD is retired; agentBLEI()'s income-buffer term, calcBLEIComponents(), the FBS gate's Yusd, and the EDC-adjusted-Gini calculation all now use WAGE_TO_USD. agentEDC() was and remains unaffected — it's a dimensionless SIU/SIU ratio that never touched either constant. This is not a compounding-loop change like v4.3's fix (these formulas are recomputed fresh each year, not accumulated), but it does feed back into wealth accumulation indirectly through the FBS gate's octave-advancement probability — see the paired fix below. At N=5,000: Full Integration median wealth rises modestly, $495,411→$526,120 (+6.2%, not a repeat of v4.3's much larger jump — this fix mostly corrects a measurement formula, not the wealth-accumulation mechanism itself); BLEI poverty falls 17.1%→12.5%; wealth poverty falls 19.5%→15.4%; Gini falls 0.536→0.518 (both Full Integration and CCO-only became more equal, not less). Effect is most visible on wage-poor cohorts specifically: the Social-Security-anchored cohorts (below) see their BLEI buffer term corrected from a ~6×-understated figure to their real income — SSDI-level median BLEI 16.4d→22.6d, retirement-level 16.6d→a median-of-medians 25.1d (mean 32.0d — see the cohort note below on why median, not mean, is the fairer summary for a right-skewed quantity across a small per-run cohort). None of these cohorts reliably cross the 30-day Threshold in the typical case; the qualitative v4.3 finding — Full Integration substantially helps this population without lifting it out of poverty by the simulation's own tier definitions — still holds, modestly narrowed, not reversed. Participant poverty (wealth) falls 15.4%→10.0%; non-participant poverty is exactly unchanged, 34.3%→34.3% — a clean confirmation the fix is behaving as intended, since non-participants never execute the FBS-gated code path this fix touches. Full N=5,000 methodology and tables in CONTRIBUTING.md.

FBS_LAMBDA recalibrated — a behavioral choice, not a dimensionally-forced one (v4.4; correction added post-release)

The FBS gate's λ coefficient has units of 1/USD by its own original comment — it multiplies a dollar-denominated surplus (fbs) to produce an advancement probability. Once fbs's dominant input (Yusd, above) grew ~6× under the wage-scale fix, λ's effective scale was left uncorrected, pushing pAdvance toward saturation (≈1) for nearly all agents regardless of BU level — measurably weakening the BU-monotonicity regression check (one seed dropped from a clean win to an exact tie at n=200). FBS_LAMBDA_LO/HI are rescaled ÷6.0456 (the precise WAGE_TO_USD/legacy-SIU_TO_USD ratio) from 0.001/0.008 to 0.0001654/0.0013233, preserving the HI/LO=8× heterogeneity shape. This entry originally called that rescale "dimensionally-necessary" — that overstated it. fbs mixes the wage-derived term that changed scale with fixed-dollar terms (BU face value, basic cost) that didn't, so fbs itself doesn't scale by one clean factor; the rescale is a chosen behavioral recalibration to restore useful advancement-probability variation, kept because the un-rescaled range — matching the BLEI paper's own published λ — already saturates (89.8–100% advancement probability) at the paper's own worked example, leaving little of λ's intended role as an individual-capability differentiator. All six VAL_TESTS pass 5/5 post-change — internal consistency, not empirical validation of these specific values. Still spec-derived, not independently sourced; open calibration status documented in CONTRIBUTING.md and the BLEI paper's own Index IV note.

True common-random-numbers pairing across Baseline / CCO-Only / Main (v4.4)

v4.2 gave the three comparison scenarios one shared latent population, but their year-by-year trajectories still ran on three independently-seeded RNG streams (seed+700001 baseline, seed+700002 CCO-only, unoffset for Main) — decorrelated from each other and from Main, not just from population construction (external audit finding). Since v4.3 made runYear() draw a fixed count and order of RNG calls per agent per year regardless of which policy toggles are active, three independent mulberry32(seed) closures — same seed, no offset — necessarily produce identical draw sequences at each (agent, year) position; baseline and CCO-only now use the same unoffset seed Main already resolves to, rather than their own dedicated streams. All three scenarios now experience identical per-agent "luck" each year (wage-variance draw, BU-spend fraction, adoption checks, appreciation noise), isolating the policy effect from Monte Carlo noise as CRN pairing is meant to. This has no effect on Main's own single-scenario trajectory — mulberry32() returns a fresh, independent closure on every call, verified directly, so creating one for baseline/CCO-only doesn't touch Main's stream position. The ablation engine already used this same same-seed-across-scenarios pattern successfully (seed0+500000 for every ablation arm); this brings the main 3-way comparison in line with it. Population construction (+700003) is unaffected.

Baseline's undocumented ×0.85 initial-wealth haircut removed (v4.4)

Baseline agents shared the same latent draw as CCO-only/Main (v4.2's paired population) but received an extra ×0.85 wealth adjustment at construction, labeled only "lower savings absent CCO" with no external citation. Since CCO hasn't happened yet at year 0, applying this before any dynamics run embedded part of the treatment effect into the counterfactual's own starting point — breaking the "matched initial agents" premise the paired-population design exists for (external audit finding). Removed; baseline now starts from literally the same wealth as its matched counterparts. Effect on baseline's own year-20 outcome is minimal — median wealth remains pinned exactly at WEALTH_FLOOR, now confirmed in 100% of N=5,000 runs (v4.3 described "more than half" the population pinned; this is the same underlying finding, now precisely quantified) — because the binding constraint is the ongoing annual cost-vs-wage gap under 20 years of 3% CPI compounding, not the year-0 starting point. Reinforces, rather than resolves, the open WEALTH_FLOOR reconsideration flagged below.

Automation exposure now paired across scenarios (v4.4)

Baseline hardcoded automation:false regardless of the user's setting, while CCO-only already mirrored it — a genuine confound whenever High Automation is enabled, since Baseline would then face a different exogenous world than the scenario it's being compared against (external audit finding: "exogenous conditions belong to the world, not the policy"). Now mirrors the user's setting like CCO-only does. No effect on the standard Full Integration reference configuration or on VAL_TESTS, both of which default automation off; only matters when a user explicitly enables it.

gamma(1) silently returned a constant, not a random draw (found during v4.4 harness work, unrelated to either audit)

The general-purpose gamma(a) rejection sampler divides by (a−1) inside a log term; at a=1 exactly this is x/0, making the acceptance test 0×log(∞)=NaN and therefore always false. Every call exhausted all 5,000 rejection iterations and fell through to return a — gamma(1) returned the literal constant 1 on every single call (confirmed: 20/20 identical samples in testing), not a random Exponential(1) draw. This directly narrows beta(6,1)/beta(1,6)drawAutomationRisk()'s high/low-risk components, used once per agent on every simulation run — and wasted the full 5,000 dead iterations per call in the process (≈2.7s of pure waste per 500-agent run, browser or harness). Fixed with the exact closed-form solution: Gamma(shape=1,scale=1) is exactly Exponential(1), so -ln(RNG()) replaces the rejection loop entirely for this case — standard, not a new formula. Population construction is now roughly 200× faster as a side effect, which is what made this release's N=5,000 study practical to run. Verified against all six VAL_TESTS post-fix.

Non-participant validation test renamed for accuracy (v4.4)

The test's own code comment always correctly described its comparator as zeroing PTF/PTH/SZH/CIP alongside CCO, not holding them fixed — but the user-facing name ("...does not worsen when CCO is enabled") read as a clean, CCO-isolated claim, and the v4.2 changelog entry describing its introduction made the same overclaim (external audit finding; corrected above). Renamed to "Non-participants under Full Integration vs. all-mechanisms-off baseline" — string-only, the comparison logic, threshold, and pass/fail behavior are unchanged.

Main wealth-accumulation loop unit fix — resolves the item open since v4.0 (v4.3)

The wage(SIU)/wealth(USD) mismatch in the main annual wealth update — left unfixed at v4.0 because a full fix proved dangerously sensitive to the conversion constant — now has a validated fix. WAGE_TO_USD ≈ 100.52 converts wage to USD (Census/BLS CPS ASEC 2023 median personal income, $42,220 ÷ 35 SIU × 12); LIVING_WAGE_ANNUAL = $49,370 anchors the cost side (a national living-wage figure for a single adult, no children — World Population Review's MIT-sourced state table, unweighted 51-jurisdiction average; see CONTRIBUTING.md for the population-weighting caveat). This replaces netting against BASE_DAILY_COST, a bare-subsistence floor correct for BLEI's poverty line but wrong for a 20-year compounding loop — that anchor produced an ~11× wealth explosion and broke BU-monotonicity (2/5 seeds) when tested. All six VAL_TESTS pass under the shipped anchor (5/5 BU-monotonicity). This is not simply a bigger-numbers fix — it redistributes. At N=5,000: Full Integration median wealth rises from $80,008 to $495,411, but EDC-adjusted Gini rises from 0.479 to 0.536 and wealth poverty rises from 14.4% to 19.5% — low-wage and non-participating agents don't share proportionally in the correction the way median-and-above-wage agents do. The Traditional Welfare Baseline is affected even more severely: median wealth falls to exactly the wealth floor (−$10,000, i.e. more than half that scenario's population is now debt-ceiling-bound by year 20), since a median wage earner's income no longer covers the new cost anchor even before the baseline's pre-existing 3% CPI compounding widens the gap further. The near-poverty (low-wealth) cohort, by contrast, benefits enormously — its median member now reaches Flourishing within 20 years in every tested run, versus never within 40 years pre-v4.3 — because most of its members have ordinary wage draws and this fix rewards wage level specifically, not starting wealth. See the new Social Security-anchored cohort study, below, and CONTRIBUTING.md's Model Architecture Feedback for the full picture, including two new open questions this surfaces (whether WEALTH_FLOOR is still appropriately calibrated, and whether the framework needs a mechanism targeting low-wage populations specifically).

runYear() RNG-coupling fix (v4.3)

The v4.2 population-pairing fix gave scenarios an identical initial population but runYear() itself still consumed a variable number of RNG calls per agent depending on which conditional branches that agent took each year (participants triggered more draws than non-participants), so agent-level trajectories still decorrelated after year 0 whenever participation composition differed. Every conditional quantity inside the per-agent loop (BU spend fraction, CIP quality bump, octave advancement, SZH→PTF induction, PTH appreciation noise, PTF Bass adoption) is now drawn unconditionally, with only the use of the drawn value gated — mirroring the v4.2 fix to agent construction. The non-participant-poverty validation check, loosened to a mean-across-seeds criterion at n=500 when this coupling was first found, is tightened back to strict per-seed agreement at the suite's standard n=200 (5/5 in testing).

Bimodal automationRisk distribution (v4.3)

Replaces uniform[0.2,1.0] — flagged as a simplification since v3.4 — with a 47%/53% mixture: high-risk agents ~ Beta(6,1) (mean ≈0.857), low-risk agents ~ Beta(1,6) (mean ≈0.143), sourced to Frey & Osborne (2013) and Autor (2015) (~47% of US employment above a 70% computerization-probability threshold, 702 O*NET occupations). Verified to have no material effect on aggregate outcomes in isolation, before being combined with this release's other changes.

Per-agent PTH tenure tracking — first step, not the full fix (v4.3)

Agents now carry pthTenure (years held in PTH residency), incremented while in PTH and reset on exit. This is tracking data only — the tenure-cohort-varying liquidity haircut itself (BLEI paper Table 1a: ~10–20% at 6 months rising to ~80–90% at 5+ years) is not implemented this pass; the flat 50% haircut is unchanged. Tracked as a good-first-issue in CONTRIBUTING.md now that the data is flowing.

Social Security-anchored income cohort study (new, v4.3)

Prompted by a review question: median-income comparisons don't show how the framework treats its actual target population for a poverty-elimination claim. SSA's 2026 COLA Fact Sheet gives three real income anchors — SSI ($994/mo), SSDI average ($1,630/mo), average retirement benefit ($2,071/mo) — now in CFG.SS_ANCHOR_* and used in a harness-based N=5,000 cohort study (agents tagged by initial wage at or below each anchor's SIU-equivalent, tracked with identical mechanics to the rest of the population — this is not a simulated Social Security mechanism, the model has no age/disability/retirement structure). Result: Full Integration dramatically improves this population's BLEI relative to baseline (20–30×) but does not lift it out of poverty by the simulation's own tier definitions — median BLEI in the teens of days for all three anchors, deep in the Precarious tier. Full table and discussion in CONTRIBUTING.md. Not yet surfaced as in-app UI (tracked as a good-first-issue). v4.4 update: these exact figures moved under the wage-scale unification (above) and should not be read as still-current — see that entry for the corrected N=5,000 numbers (median-of-medians BLEI now ~20-25d across the three anchors, no longer literally "teens of days" for all three; the relative-improvement multiplier over Baseline also fell from ~20-30× to ~7-10×, since Baseline's own BLEI is computed with the same corrected wage-buffer term and rose too, from near-zero to a few days. The qualitative conclusion — substantial relative improvement, no cohort reliably escapes poverty by the tier definitions — is unchanged; only the specific multiplier and day-counts are stale here.)

README.md synced to v4.2; large-N reconfirmation published (v4.2)

The project README.md had not been updated since v3.3 and stated several claims this pass corrected against the actual source: the CCO conversion formula as C = B₀ × 2^O (actual mechanism is linear in octave, see the note above), Gini as a closed-form decay expression (the actual metric is the standard Gini computed on EDC-adjusted net wealth in calcMetrics()), the recession severity mode as ≈0.86/14% loss (corrected below to 0.90/10%), and PTF's role as a "40-60% overhead reduction" plus a "2.64x BU food premium" (PTF is a 12-16% cost-reduction mechanism only; 2.64x is CCO's ε_food, an unrelated parameter). The README's Output Metrics table previously presented internal design-target constants as if they were achieved simulation output; it now cites the 5,000-seed large-N study (seeds 1-5000, matched Full Integration / CCO Only / Traditional Welfare runs) published in the Replication Framework's Performance Comparison section, with a note on where measured output still falls short of the original design targets (Gini and wealth-poverty rate) and the likely cause (the wealth-initialization distribution's own inherent Gini ≈0.60 pre-dynamics).

Common-random-numbers population pairing (v4.2)

The main run, "CCO Only," and baseline comparisons now share one canonically-drawn latent population instead of three independently-sampled ones — closing an item raised in the Aug 2026 external review ("the baseline and CCO-only populations are not actually the same individuals") and in CONTRIBUTING.md's Model Architecture Feedback. The earlier objection that pairing "isn't well-defined once maxOct/maxMult differ in support between scenarios" is correct against the scaled OUTCOME (octave/quality) but not the underlying draw: the pre-policy shape variate is now shared and scaled independently per scenario, which is what a "same individuals, different policy" comparison needs. This also fixed a genuine, independently-found bug: makeAgent()'s three eligibility draws used short-circuit &&, so the number of RNG calls consumed during agent construction depended on which subsystems were toggled on — two scenarios built from the "same" seed but different toggle states (e.g. the validation suite's PTF-on vs PTF-off check) silently diverged in every draw after the first toggle difference, not just membership. Reproducibility note: this changes the RNG call sequence — a given seed no longer reproduces v4.1's numeric output. New seed-42 reference figures are in the version-history comment block, near the top of the source.

Structural System Stability metric (v4.2)

Replaces the trend-plus-noise heuristic flagged since v3.6 (see below) — a CONTRIBUTING.md good-first-issue. The displayed value is now the inverse coefficient of variation of median wealth and median BLEI over the final quarter of the run (no RNG call, no manual per-mechanism bonus): if a mechanism genuinely stabilises outcomes it now shows up endogenously as lower volatility, since every mechanism already feeds wealth and BLEI within runYear(). The baseline and CCO-Only comparison rows, previously hardcoded at "~65%"/"~88%" regardless of actual configuration, now compute the same metric from their own trajectories. This formula has its own limitation, surfaced and disclosed in v4.4 — see Known Limitations.

Validation suite: multi-seed robustness + two new checks (v4.2)

The original four checks each ran once, on one hardcoded seed — unable to distinguish a genuine structural property from a lucky draw. All four now run across five seeds and require unanimous agreement (all four are 5/5 robust). Two checks were added: a CONTRIBUTING.md good-first-issue verifying non-participant poverty doesn't worsen when CCO is enabled (compares against an all-mechanisms-off baseline, not a true CCO-isolated counterfactual — PTF/PTH/SZH/CIP are zeroed in the comparator, not held at the tested scenario's rates; renamed for accuracy in v4.4, see Known Limitations — uses a larger population and a mean-across-seeds criterion rather than per-seed agreement — see the code comment above VAL_TESTS for why, a newly-documented RNG-coupling property of runYear() under Known Limitations), and a structural-invariants check (population conservation across BLEI tiers, octave/wealth-floor/participation bounds, Gini bounds) as a regression net for future changes. Renamed "Internal Validation Suite" → "Internal Consistency & Behavioral Test Suite" and labeled against the ODD Level 1–5 validation hierarchy (this suite covers Levels 1–3; Levels 4–5, external empirical validation, remain open — see Known Limitations) since "validation" on its own overstated what these checks establish.

"Policy-grade" language tightened (v4.2)

Title, meta description, and social-share tags previously called this a "policy-grade" simulation while the CSV export and Known Limitations already called it an exploratory ABM not intended as a forecast — an internal inconsistency. Now consistently "research-oriented exploratory agent-based simulation... for comparative policy analysis" throughout, matching the more defensible framing that was already used elsewhere in this document.

PTF attribution leak in paired-population ablation (v4.1)

The v4.0 paired-population ablation redesign (below) intentionally builds every removal scenario's agents under the FULL config so membership flags (inCCO/inPTF/inPTH) match across scenarios for RNG-pairing — correct for the simulation mechanics, which already re-check the relevant system toggle everywhere they consume those flags. But agentBLEI()'s SZH+PTF synergy term trusted a.inPTF directly with no ptfOn parameter to check against, unlike ccoOn/pthOn, which already gate a.inCCO/a.inPTH everywhere they're used (independently re-audited in this pass and confirmed unaffected). Result: the "Remove PTF" ablation result could retain a synergy bonus it shouldn't have whenever SZH was also active — worth roughly 12 BLEI days per affected agent in testing — understating PTF's true contribution on the Attribution chart. Fixed by threading ptfOn through agentBLEI()/bleiMetrics(), mirroring how pthOn already works; normal (non-ablation) runs are numerically unaffected. Found in a Claude (Anthropic) chat audit, Aug 2026.

Illustrative reference-run label was never shown (v4.1)

IS_REF_RUN was set true by the page-load auto-run (v3.4) but nothing ever read it, so the "📊 Illustrative reference run — seed 42…" banner stayed display:none permanently since its introduction — general-purpose neighbors (the Exploratory-simulation notice above the KPIs) covered for it, which is likely why this went unnoticed across several audit passes. Wired up in finish(): the flag is read once, to show the banner only for the genuine auto-loaded run, and reset immediately after so it can't linger into a later manual or chained Monte Carlo run.

Stale UI hint text corrected against current formulas (v4.1)

Several small strings had drifted from the mechanics they describe. The recession hint stated a 2–4 year / 65–85% income-multiplier range; the actual beta(5,2) formula (unchanged since v3.3, and correctly described elsewhere in this panel) produces 1–3 years / 70–95% — apparently a leftover from before that v3.3 change, missed by every subsequent audit including the one that corrected this same distribution's mode figure elsewhere on this page (below). The Max Octave hint described conversion capacity as "C = C₀ × 2ⁿ"; the actual v4.0 mechanism (above) is linear in octave/maxOct, reaching exactly the quality multiplier ceiling at max octave — an exponential form would hit 512× at octave 9, far past that ceiling — so the hint now describes the real shape. The Quality Multiplier Ceiling's static default read "14.58×" against the correct "14.56×" (9×1.618) shown one field above it; cosmetic, since updateEffMax() corrects it as soon as the reference preset auto-loads, but wrong in markup. The poverty-chart baseline caption asserted baseline recessions are unconditionally "enabled," no longer accurate once v4.0 paired baseline's shock exposure to the user's own toggle. OAT sensitivity's PTF-share perturbation used range [0,0.35] instead of the slider's actual [0.05,0.35], a minor overstatement of that one parameter's ±20% step.

Octave advancement, conversion capacity & PTF diffusion (v4.0)

Octave advancement is now FBS-gated (P(advance)=1−exp(−λ·FBS), a per-agent λ~U(0.001,0.008)) rather than a fixed probability — an agent at FBS=0 can no longer advance regardless of BLEI. Octave now governs CCO conversion-rate capacity (quality modulates the realised rate within it); previously octave had no role in conversion at all. PTF adoption gained a Bass (1969) imitation term based on current adoption share. External review (Refine.ink, Aug 2026) + BLEI paper §8 Table 6.

PTH Acre Equity payment contribution & SZH network-density gating (v4.0)

A documented share (25%) of PTH's annual housing-cost saving now routes into Acre Equity instead of landing entirely as liquid relief — the "payments build equity" mechanism was previously absent (appreciation-only); no new wealth is created, this re-routes where an already-counted saving lands. SZH's synergy coefficient θ is now network-density-gated (0 below 55% PTF density, scaling to 0.25 at 90%+) rather than plain-linear in coherence.

Dimensional (unit) coherence in BLEI, FBS & Gini (v4.0)

agentBLEI(), calcBLEIComponents(), the new FBS gate, and the Gini net-wealth adjustment now convert wage (SIU) to real USD via a single derived constant, SIU_TO_USD = (BASE_DAILY_COST×365)/SIM_COST_SCALE, before mixing it with dollar-valued terms — previously a raw SIU number was added directly into USD sums. agentEDC()'s saturation constants were rescaled so EDC responds to income above the median instead of sitting at a constant value for every realistic wage. The main wealth-accumulation loop was deliberately left unchanged — see Empirical Calibration below.

Baseline & CCO-only comparison isolation (v4.0)

Baseline and CCO-only comparison populations are now generated independently from their own scenario parameters instead of being copied from the tested scenario's agents (which previously let e.g. the main run's Max Octave slider silently change the "baseline" comparison). Baseline's shock exposure is now paired with the main scenario's toggle (was hardcoded on) and its inflation anchored to the documented 3% CPI baseline (was copying the user's slider). "CCO Only" now mirrors the user's own CCO settings rather than a fixed reference calibration, isolating the marginal effect of PTF/PTH/SZH/CIP. When shocks are enabled, all three trajectories now draw from the same precomputed recession path ("paired shocks").

Monte Carlo, ablation & OAT statistics (v4.0)

Fixed a flag-clearing bug that made every 3×/10×/50× Monte Carlo request silently execute exactly once with zero results collected — the MC controls were completely non-functional. Ablation/attribution now uses a paired population and paired RNG stream across every removal scenario plus a matched "full system" reference run, with signed deltas (a subsystem whose removal improves BLEI now shows as negative instead of being clamped to zero). OAT sensitivity now perturbs all five parameters by a uniform ±20% of each parameter's own slider range, replacing a mix of relative and fixed-percentage-point steps that didn't share a common scale.

Validation suite parameter mapping & CI labeling (v4.0)

Two validation tests silently tested nothing: the participation-threshold test passed {part:78}/{part:45} to a function that reads partRate, so both runs used the same 78%; the inflation test passed {inflRate:3}, read as a 0–1 fraction — 300%/yr, not 3%. Both fixed. The 10×/50× "Publication CI" label overstated what those bounds capture (a stochastic-error range at fixed parameters, not a full outcome-uncertainty interval) — relabeled "Stochastic CI" with copy stating the scope.

Wealth ratio near-zero guard & OAT params mutation (v3.9)

The p90/p10 wealth ratio only guarded against p10 ≤ 0, so a near-zero p10 produced a misleadingly large finite ratio instead of "∞" — threshold changed to <$100. Separately, OAT sensitivity's base-params setup mutated the object returned by getCurrentParams() directly; it now builds a fresh object instead.

Comparison-run RNG isolation (v3.8)

The baseline and CCO-only comparison trajectories previously ran on the same shared RNG stream the main trajectory consumed next, so changing years or agent count shifted the main run's random sequence at a fixed seed. Each comparison run now uses its own seed-derived stream (mirroring the existing ablation RNG-swap pattern), restored before the main trajectory begins.

Double preset-apply on page load (v3.7)

The DOMContentLoaded and load listeners both called applyPreset('reference'), silently re-applying all default parameters a second time before the first run executed. The load listener now only sets the reference seed/flag and calls runSim().

Chart screen-reader labels (v3.7)

All 11 Chart.js canvases previously had no accessible name — a sighted-only presentation of every result. Added role="img" and a descriptive aria-label to each.

In-app glossary panel (v3.7)

Added a collapsible acronym glossary above Scenario Presets, mirroring the Key Concepts accordion on the replication page, so first-time users don't have to leave the tool to look up CCO/PTF/PTH/SZH/CIP and related terms.

PTF slider relabeled & documented as initial condition (v3.6)

The slider was labeled "PTF market share" but only set the initial adoption probability at t=0; independent per-agent adoption checks in runYear() mean the realised final share can and does exceed the slider value. Relabeled to "Initial PTF share" in the UI, CSV export, and run-configuration summary, with a slider caption explaining the organic-growth behaviour.

System Stability tooltip (v3.6)

Added an ⓘ tooltip on the System Stability KPI disclosing that it is currently a trend+noise heuristic rather than a structural metric, with the exact formula documented in Known Limitations below.

Mobile table overflow (v3.6)

Comparison and milestone tables carried a hardcoded min-width:640px, forcing horizontal scrolling on every mobile viewport regardless of actual content width. Removed the fixed minimum and added a small-viewport rule that shrinks font size and cell padding instead.

Cancel control for long runs (v3.6)

Previously the only way to stop a 50× Monte Carlo run once started was to refresh the page. Added a Cancel button, checked at the top of each simulated year and between chained Monte Carlo runs, that stops cleanly and restores the UI without a reload.

Implicit global declared (v3.6)

IS_REF_RUN was assigned inside the page-load listener without a prior declaration, creating an implicit global in non-strict mode. Declared explicitly alongside the other module-level state variables.

Missing space in contextual insight string (v3.6)

The "enable remaining systems" insight card rendered as "Enable SZH+CIPfor full integration" — a missing space before "for". Fixed.

Version/citation consolidation & DOI (v3.5)

Exported CSV/JSON files previously self-reported "v3.3" in headers, filenames, and metadata while the page displayed v3.4 — a version-string drift bug. Fixed by introducing a single META object as the source of truth for version, DOI, citation, and URL; all exports now read from it. Archival DOI (10.17605/OSF.IO/QWTE2) added to schema.org metadata, footer, References, and both export formats.

Preset internal naming (v3.5)

Internal key PRESETS.optimal renamed to PRESETS.reference throughout (definition, button id, PRESET_IDS, OAT sensitivity mini-runs). UI-facing labels ("Full Integration", "reference run") were already correct; this closes the gap between internal code and displayed terminology.

Effective max quality multiplier indicator (v3.5)

Added a live label under the Quality Multiplier Ceiling slider showing the Phi-adjusted effective maximum (e.g. "Effective max with Phi: 14.58×"), updating on slider drag and Phi toggle. Previously the 1.618× Phi bonus on top of the stated ceiling was undocumented in the UI.

Seed range clamp & EDC documentation (v3.5)

initRNG(): now enforces the same 0–999999 range as the seed input's HTML min/max, not just a NaN check. agentEDC(): added a comment documenting that the 18/1100/820 constants are scenario-calibrated design targets (chosen so EDC lands within CFG.EDC_BASELINE_LO/HI at median wage for each tier), not derived from a closed-form model or external data.

Gini — negative wealth & zero-wealth (v3.2/v3.3)

v3.2: Gini computed on wealth clamped to ≥0 (WEALTH_FLOOR=−$10K broke standard formula). v3.3: totW=0 → Gini=0, not 1. (Old ||1 fallback incorrectly returned 1 for zero-wealth edge case.) Gini measures distribution shape; all agents at zero = perfect equality of deprivation. BLEI poverty (% <30d) captures the poverty level that Gini misses here.

Wage growth diminishing returns (v3.3)

Fix: Stability premium × 1/(1+0.5·max(0, wage/35−1)). Prevents structural compounding at high incomes. BLEI is purely measurement; the premium reflects the underlying stability it measures. Diminishing returns grounded in Mullainathan & Shafir (2013) + Carroll (1997): marginal benefit is largest at low-to-median wages.

Recession severity distribution (v3.3; mode figure corrected v4.0)

Fix: Uniform distribution replaced by beta(5,2) over [0.70,0.95] — mild recessions most common, tail to 0.70 (30% loss, analogous to 2008–09). v4.0 correction: this entry previously stated the mode as "≈0.86 (14% income loss)", which is arithmetically wrong — beta(5,2)'s mode is (5−1)/(5+2−2)=0.80, giving a multiplier mode of 0.90 (10% loss). The distribution's mean (≈0.88, ~12% loss) and median (≈0.88, ~11.6% loss) are close to the cited NBER target and are unaffected; only the mode figure was wrong, and only in this prose, not in the beta(5,2) formula itself (external review, Refine.ink, Aug 2026, caught this across all three project pages). Calibrated against NBER post-WWII recession data: median US recession ≈ 12% peak income loss. Source: NBER Business Cycle Dating Committee.

NaN/Inf guards, percentile interpolation, SIM_COST_SCALE (v3.3)

NaN guards in agentBLEI, agentEDC, runYear, calcMetrics. p10/p90 now use proper linear interpolation (not index rounding). ANNUAL_BASE_COST renamed to SIM_COST_SCALE to avoid apparent contradiction with BASE_DAILY_COST ($68.33/day ≈ $24,941/yr vs 1,500 SIU simulation scale).

agentEDC income proxy & lognormal stability (v3.2)

EDC: Switched from wealth/60 proxy to actual agent wage (consistent with BLEI v3.1 fix). lognormal: Math.max(1e-14,1−RNG()) protects against log(0)=−Infinity on seeds where RNG()=1. gamma(): 5,000 iteration cap prevents potential infinite loop.

Comparison RNG & PRESET crash (v3.2/v3.3)

v3.2: CCO comparison agents use deterministic index-based participation (not RNG()<0.78) — preserves seed reproducibility. v3.3: PRESETS now includes 'hiAI'; applyPreset() guards against undefined preset with console.error; all 5 preset buttons correctly highlighted.

📊 Empirical Calibration & Mechanism Documentation
Daily vs. simulation cost scales — what v4.0 fixed and what it deliberately didn't

BASE_DAILY_COST ($68.33/day, BLS CES 2023) and SIM_COST_SCALE ($1,500, calibrated ABM scale — NOT a dollar figure) are two different units. An external review (Refine.ink, Aug 2026) correctly flagged that wage (SIU) was being added directly into USD-typed sums in several places. Fixed in v4.0: agentBLEI, calcBLEIComponents, the FBS advancement gate, and the Gini net-wealth adjustment now convert wage to USD via a derived constant, SIU_TO_USD = (BASE_DAILY_COST×365)/SIM_COST_SCALE ≈ 16.6 — these formulas don't compound over time, so a conversion constant there is safe. Deliberately NOT changed: the main wealth-accumulation loop (wage×12 vs. SIM_COST_SCALE-based cost) — we built and tested that fix, and because wage compounds against cost over up to 30 years, it turned out to be extremely sensitive to the conversion constant (a ~3.5× range of candidate values swung 20-year outcomes from universal wealth-floor collapse to implausible multi-million-dollar median wealth). Getting that constant right is a joint recalibration of the wage distribution, cost scale, and every target metric against real income data — a substantial project of its own, not something to guess at inside a bug-fix pass. The main loop still uses the wage×12/SIM_COST_SCALE ratio exactly as before (worked example: 35 SIU/month → annual SIU income 420 → ratio 420/1,500 = 0.28; with CCO+PTF+PTH cost factors ≈0.457, effective cost 686 → ratio ≈0.61) — this is now a documented simplification rather than a silent unit mismatch. Standard ABM calibrated-unit convention (Epstein & Axtell, 1996); base daily cost sourced from BLS CES 2023 (bls.gov/cex).

BU wealth creation — counterparty accounting

BU → quality conversion does not create wealth ex nihilo. PTF businesses accept BUs and provide real goods/services (food, utilities) at cooperative prices. Quality multiplier reflects productivity gains distributed to workers via cooperative ownership (Mondragon model, Whyte & Whyte 1991). Conversion economy circulates within the PTF network. v4.0: external review correctly noted the engine credited conversion proceeds without debiting any treasury/production account. As a first step, cumulative conversion proceeds are now tracked and surfaced in CSV/JSON export (Conversion Ledger) for transparency. A genuine aggregate production constraint — one that could ration agent-level conversion when exhausted — is a further economic-modelling design decision (production function, capacity limits, failure behaviour) that isn't implemented yet; see Known Limitations.

PTH Acre Equity — payments now build equity (v4.0)

THREE separate PTH benefits as of v4.0: (1) housing cost reduction (35% of SIM_COST_SCALE), (2) a share (25%) of that cost saving routed into Acre Equity — the "payments build equity" mechanism the docs described but the engine previously didn't implement (it was appreciation-only) — and (3) Acre Equity appreciation, where wealth += appreciation × 0.5 is not double-counting: it represents the accessible-liquidity fraction (50% haircut), with full appreciation tracked to acreEquity (illiquid) and half flowing to liquid personal wealth. The new equity contribution re-routes an already-counted saving rather than creating new wealth, so it doesn't reintroduce double-counting. Consistent with Burlington CLT documentation (Champlain Housing Trust).

Framework design intent — macro constraints

The framework is explicitly designed to approach universal prosperity for the coming automation wave, with BU as treasury-backed community infrastructure. Absence of housing scarcity and fiscal limits is a stated hypothesis — that cooperative institutions structurally reduce these frictions — not a modeling oversight. This is a documented divergence from traditional macro models.

⚠ Known Limitations
No demographic structure

Agents lack age, retirement, disability, household size, or mortality. Acceptable for structural scenario comparison; not suitable for policy forecasting requiring life-cycle dynamics. Future: age cohorts and household transitions (see CONTRIBUTING.md).

No direct agent-to-agent interaction

All social effects mediated by aggregate zone parameters (SZH) rather than explicit networks. A small-world network structure would better model PTF zone clustering and SZH coherence. Noted as a future development direction in CONTRIBUTING.md.

automationRisk distribution — resolved in v4.3 (flagged v3.4)

Through v4.2, automationRisk ∈ [0.2, 1.0] was drawn from a uniform distribution — real automation exposure is highly bimodal and occupation-dependent (Frey & Osborne, 2013; Autor, 2015), and the uniform assumption understated polarization in High Automation scenarios. As of v4.3, it's a 47%/53% mixture (Beta(6,1) high-risk / Beta(1,6) low-risk) matching that literature's occupational split — see Cumulative Bug Fixes, above. Occupation-stratified (not just bimodal) risk remains a further-refinement item in CONTRIBUTING.md.

One-at-a-Time (OAT) sensitivity is not Sobol/LHC

OAT sensitivity varies one parameter at a time ±20% of its own slider range (v4.0: uniform across all five parameters — see Cumulative Bug Fixes) and records the poverty and BLEI response from actual model runs. It captures first-order single-parameter effects only. Parameter interactions and higher-order effects are not quantified. For rigorous uncertainty quantification, use the CSV export with external Sobol analysis in Python/R (see CONTRIBUTING.md).

System Stability rewards a stagnant floor as much as a thriving population (updated v4.4)

Historical note: through v4.1 the displayed value was a heuristic, stabBase = improving ? 0.88 : 0.60 plus RNG()×0.08 noise — not derived from wealth variance, BLEI volatility, or agent-state transitions (v3.6 flag). Resolved in v4.2: structuralStability() is the inverse coefficient of variation of median wealth and median BLEI over the run's final quarter — no RNG call, no manual per-mechanism bonus. This formula has its own honest limitation, not previously disclosed here: a population with genuinely flat, unchanging outcomes scores as maximally stable, whether that flatness reflects a thriving equilibrium or a population pinned at a floor with nowhere left to fall — coefficient of variation can't distinguish the two. In the v4.4 N=5,000 study, the Traditional Welfare Baseline — median wealth pinned exactly at WEALTH_FLOOR in 100% of runs by year 20 — scores 99.0% stability, higher than Full Integration's 88.6%, precisely because a hard floor has near-zero variance left to measure. Read this metric as trajectory steadiness, not as an endorsement of the outcome it describes, and always alongside the poverty and BLEI figures next to it, never in isolation. Full N=5,000 comparison in CONTRIBUTING.md.

Main wealth-accumulation loop unit fix — resolved in v4.3, with new open questions

v4.0 fixed wage/USD unit mixing in BLEI, FBS, and Gini but deliberately left the main runYear() wealth-accumulation step on its pre-v4.0 SIU-scale convention, because a full fix proved dangerously sensitive to the conversion constant. v4.3 ships a validated fix (WAGE_TO_USD/LIVING_WAGE_ANNUAL — see Cumulative Bug Fixes, above) after finding an anchor that passes all six VAL_TESTS. This resolves the unit-simplification item but opens two new ones, not yet resolved: whether WEALTH_FLOOR = −$10,000 is still an appropriate floor now that the cost anchor it's measured against roughly doubled (median Baseline wealth now sits exactly at that floor, not just an occasional insolvency case), and whether TARGET_WEALTH/TARGET_POVERTY/TARGET_GINI — set against the old loop — need their own reconsideration against the structurally different new baseline. Both flagged in CONTRIBUTING.md as framework-level decisions, not resolved here — v4.4 adds an in-app pointer to this caveat directly on the affected KPI badges (Gini, Wealth, Stability, Flourishing, EDC — the ⓘ icons), but does not pick new target values. (Separately: BLEI/FBS/Gini's own wage-to-USD conversion, left on the older SIU_TO_USD approximation since v4.0, is unified onto WAGE_TO_USD in v4.4 — see Cumulative Bug Fixes, above. That's a different unit issue from the one this entry covers.)

Framework does not yet address low-wage populations specifically (new finding, v4.3)

The new Social Security-anchored cohort study (Cumulative Bug Fixes, above) found that Full Integration does not lift a low-wage cohort out of poverty by the simulation's own tier definitions, even though every existing mechanism already applies to it equally — it helps this population enormously in relative terms (originally measured at 20–30× the baseline's BLEI; recomputed at ~7–10× under v4.4's wage-scale unification, since Baseline's own BLEI moved too — see that entry) without coming close in absolute terms. Whether this points to a genuine mechanism gap (e.g. wage-conditional BU scaling) or accurately reflects the framework's intended scope is an open question for the framework's authors, not resolved here — see CONTRIBUTING.md.

CCO conversion proceeds are tracked but not production-constrained

BU → wealth conversion proceeds are credited to agents without debiting a modelled treasury, PTF balance sheet, or production account — external review correctly flagged this as an open stock-flow accounting gap. v4.0 adds transparency only: cumulative conversion proceeds are tracked and exported (CSV/JSON "Conversion Ledger"). A genuine aggregate production constraint — with a defined production function, capacity limits, and rationing behaviour when exhausted — is a further economic-modelling design decision not implemented here; see CONTRIBUTING.md.

No external validation

Parameters calibrated against analogues (Alaska PFD, CLT network, Mondragon) but outcomes not validated against deployment data. Phase 4 roadmap: validation against Fed SCF, CPS, ACS, BLS CES, and OECD inequality trajectories. Required before claims of predictive validity.

📚 References & Citations click to expand
Autor, D.H. (2015). Why are there still so many jobs? The history and future of workplace automation. Journal of Economic Perspectives, 29(3), 3–30. [automation risk]
Bass, F.M. (1969). A new product growth model for consumer durables. Management Science, 15(5), 215–227. [PTF diffusion model]
Carroll, C.D. (1997). Buffer-stock saving and the life cycle/permanent income hypothesis. Quarterly Journal of Economics, 112(1), 1–55. [wage diminishing returns]
Champlain Housing Trust. Community Land Trust Program. champlainhousingtrust.org. [PTH 50% liquidity haircut]
Epstein, J.M. & Axtell, R. (1996). Growing Artificial Societies: Social Science from the Bottom Up. MIT Press. [ABM calibrated-unit convention]
Frey, C.B. & Osborne, M.A. (2013). The Future of Employment: How Susceptible Are Jobs to Computerisation? University of Oxford. [automationRisk calibration]
Grimm, V., et al. (2010). The ODD protocol: A review and first update. Ecological Modelling, 221(23), 2760–2768. [ABM documentation standard]
Johnson, D. & Claude (Anthropic). (2026). Basic Living Economic Index (BLEI). Better To Best Research Hub. CC BY 4.0. ↗ paper
Johnson, D. & Claude (Anthropic). (2026). Compassionism Framework Simulation. Better To Best Research Hub. CC BY 4.0. ↗ DOI: 10.17605/OSF.IO/QWTE2. [archived version of this tool]
Jones, D. & Marinescu, I. (2018). The labor market impacts of universal and permanent cash transfers. NBER Working Paper 24312. [Alaska PFD analogue]
Mullainathan, S. & Shafir, E. (2013). Scarcity: Why Having Too Little Means So Much. Times Books. [FBS bandwidth constraint, wage growth]
NBER Business Cycle Dating Committee. U.S. Business Cycle Expansions and Contractions. nber.org. [beta(5,2) recession calibration]
U.S. Bureau of Labor Statistics. (2023). Consumer Expenditure Surveys. bls.gov/cex. [BASE_DAILY_COST $68.33/day]
Whyte, W.F. & Whyte, K.K. (1991). Making Mondragon. ILR Press. [BU conversion counterparty model]