CLI Reference¶
The research CLI for HOURS is utils/eoh_cli.py. Run from the repo root:
Add --no-color to any command to strip ANSI output for piping or logging. Most commands support --format table|csv|json.
arc¶
Sweep ε from 0 to 0.99 — EOH by domain, registration share, TEH created, basket price, fiscal solvency.
dashboard¶
Color-coded system health snapshot: Structural Conditions I–IV, EOH health, fiscal health.
params¶
Inspect and modify the EohParams calibration. Changes are persisted to utils/_params_state.json and applied to all subsequent commands.
python3 utils/eoh_cli.py params show # all values
python3 utils/eoh_cli.py params set KEY VALUE [--reason TEXT] [--dry-run]
python3 utils/eoh_cli.py params diff # active overrides
python3 utils/eoh_cli.py params reset # clear all
Preview before persisting:
Multi-command workflow:
python3 utils/eoh_cli.py params set capital_stock_teh 4000000000 --reason "high-capital scenario"
python3 utils/eoh_cli.py arc --points 20
python3 utils/eoh_cli.py dashboard --epsilon 0.60
python3 utils/eoh_cli.py params reset
scenario¶
Run or list stress-test scenarios.
python3 utils/eoh_cli.py scenario list
python3 utils/eoh_cli.py scenario run NAME [--format table|csv|json]
scenario list is the authoritative list — it is generated from the
registry, prints each scenario's own options, and cannot fall behind. The table
below names the families and a representative of each; it is not exhaustive.
| Family | Representative scenarios |
|---|---|
| Arc coherence | sweep |
| Shocks | automation_failure, demographic_shock, ecological_spike, labor_income_shock, compound_shock, capital_loss |
| Maintenance & recovery | maintenance_crisis, care_delay, recovery |
| Long run | canonical_arc, trust_stress, transition, indust_baseline, indust_recovery |
| Land / GUF | guf_integration, guf_writedown, guf_sweep, guf_magnitude, servicing_census, land_tenure |
| One collective, end to end | collective — the documented institutional entry point |
| Measurement and reporting | obligation_accounts, personal_floor, labour_epsilon, frame, feasibility |
| The register itself | verification_cost, verification_band, register_capture |
A flag is read or refused. --epsilon is refused by a scenario whose
output is the same at every ε — an arc it sweeps itself, or measured and
reference data — rather than accepted and ignored; feasibility reads it only
with --adult-capacity or --adult-share. Frame flags follow the same rule.
See Running Scenarios for Python API usage.
frame — running on your own frame¶
Every scenario that takes a population runs on a frame, as does
corridor band: a population, its age mix, its adult labour capacity, its
capital, its land, its Trust and its ε. Each prints the inputs it READS, with
where each came from, and refuses a flag it does not read — the shocks read the
age mix and labour supply; the long-run, Trust and simulation scenarios read
population, capital, Trust and ε; indust_* read population and ε; the arcs
(canonical_arc, transition, thermal_load) sweep ε themselves and refuse
--epsilon. On a named frame, canonical_arc, trust_stress, transition
and measured_sim also charge the frame's land fee in every period, capped at
what the wage can pay, as stationarity does. Without a frame, collective
runs the urban archetype's own parcel inventory. On --frame / --frame-file
it runs the frame's land, labour supply and private parcels instead. The
parcel-based GUF scenarios (guf_integration, guf_writedown) take only the
frame's ε, because their land is their own parcel sample:
| Kind | Meaning |
|---|---|
supplied |
you gave it — a flag, or your frame file |
measured |
read from a dataset the repo ships for a built-in frame (--frame us: Census ages, MTUS capacity, both ε instruments, BEA stock ages, EIA energy) |
derived |
computed from other inputs, all of them supplied or measured |
derived (partly from defaults) |
computed, but leaning on a framework default (e.g. a per-head intensity) |
derived (from defaults) / default |
the framework's reference value — it says nothing about your frame. A default whose source begins charter choice (the Trust's opening balance, the retirement register, who carries ecological work) is a governance setting, not missing data |
Read a result only as far as its inputs go: an outcome built on default rows
is a statement about the reference collective, not about yours.
On --frame us the capital is the US stock: BEA's inventory at the midpoint of
conversion_band(), the derived dollars-per-hour band. Each scenario that reads
capital also reports its verdict at both ends of that band ("at both ends of the
conversion band"). --bea-usd-per-teh or --capital-stock states your own.
# What a frame resolves to, every input labelled
python3 utils/eoh_cli.py frame show --frame us
# Start your own frame from the US one, then replace what you have measured
python3 utils/eoh_cli.py frame show --frame us --format json > my_frame.json
# Run a shock and the corridor on it
python3 utils/eoh_cli.py scenario run demographic_shock --frame-file my_frame.json --shock-type aging --shock-magnitude 0.2
python3 utils/eoh_cli.py corridor band --frame-file my_frame.json
The frame file is JSON with any of: name, population, age_fractions
(every AGE_GROUPS group, summing to 1), epsilon (a number, or
{"low": a, "high": b}), capital_teh, land_hectares,
adult_capacity_h_yr, utilization, trust_balance, retirement_age,
retired_share, years_in_collective. Anything else is refused, never
patched. What you leave out is derived or defaulted — and
labelled so. ε is never imputed: without a reading it runs at the
reference value, labelled default.
Shipped and constructed frames. A frame file is the one intake — a
country's, an institution's, or a constructed scenario's. eoh frame shipped
lists the files that ship with the repo (--write regenerates them from the
module that owns each), and --frame-file NAME runs one. indust_overbuilt is
CONSTRUCTED, not measured: an overbuilt industrial collective (10× capital per
head, an aged stock, ecosystem health below the spike threshold) whose
ecological work its people carry rather than the GUF. Constructed frames are
fictitious on purpose — some extreme, to test the framework's bounds and how it
handles collapse; a combination that looks unworkable and still reads stable is
itself a finding. A frame file may also state ecosystem_health,
capital_age_ratio and ecological_carried_by_people; declared carried, the
health deficit over the frame's land is priced as a restoration obligation and
carried as labour with the recurring ecological work, in the shocks, the band
and the overbuild floor.
python3 utils/eoh_cli.py frame shipped
python3 utils/eoh_cli.py corridor band --frame-file indust_overbuilt
python3 utils/eoh_cli.py scenario run capital_loss --frame-file indust_overbuilt --capital-fraction-lost 0.2
Retirement as a register event is a governance choice, so it is off unless
you ask for it. With --retirement-age (bare: the charter default, or give an
age within the elderly band), members past that age join the guarantee at the
elderly obligation. --years-in-collective sets their claim through the
framework's vesting curve — 0 is no claim, the same as leaving it off. The
retired share is measured from Census ages where the frame has them, and
labelled as leaning on the Census age profile where it does not.
python3 utils/eoh_cli.py scenario run demographic_shock --frame us --shock-type aging --shock-magnitude 0.04 --retirement-age
python3 utils/eoh_cli.py scenario run demographic_shock --frame us --retirement-age 70 --years-in-collective 0
A disaster that destroys capital — a wildfire, flood or earthquake — is
capital_loss. The share destroyed is written down (D1: the TEH it embodied is
reported, not charged to the Trust), its upkeep leaves the obligation, and the
machine work it did falls to people. By default machine capability falls by the
same share as the capital, which assumes the loss is spread across the stock;
--capability-fraction-lost sets it apart (a fire that takes houses and spares
the grid). Rebuilding is a choice, off unless --rebuild-years is given; when
on, it is booked as the reconstruction obligation (reconstruction_obligation
in total_eoh and the pipeline) and the result says rebuild: on. The
result separates capacity (the machine stock that can still run — only a
rebuild restores it) from efficiency (the share of people's work actually
done — labour restores it), so a broken plant and an unstaffed one do not read
alike. A wildfire also burns ecosystem: compound_shock --ecology-collapse
--capital-fraction-lost F applies both to one state.
python3 utils/eoh_cli.py scenario run capital_loss --frame us --capital-fraction-lost 0.05 --rebuild-years 5
Deferred upkeep against the overbuild floor. On a frame,
maintenance_crisis reads every year against the overbuild floor — whether
the apparatus still saves more hours than it costs its members against
autarky. Deferred upkeep pushes toward the floor two ways: the compounding
backlog adds upkeep, and the neglected stock, its condition falling, abates
less. The table shows the condition ratio and the margin each year, and the
year the stock is past saving: from then on catching up the neglect costs more
labour than rebuilding. That year is derived, not set — an older or more
upkeep-intensive stock reaches it sooner — and the frame's capital age sets
where the stock starts. On --frame us that age is measured: BEA's average
ages over BEA's service lives (frame show --frame us gives the band and what
is excluded).
python3 utils/eoh_cli.py scenario run maintenance_crisis --frame us --fulfilment-fraction 0.5 --periods 30
When ε is a range (a frame-file range, or the US instruments), the
scenario also runs at both ends and prints each outcome. Where they differ,
the difference is the result; when the instruments DISAGREE, the midpoint is
labelled as not a reading. Precedence: a flag, then --frame-file, then
--frame, then the default. A scenario that reads no frame refuses frame
flags rather than ignoring them.
simulate¶
Multi-period simulation with period-by-period state table.
python3 utils/eoh_cli.py simulate [--periods N] [--epsilon ε] [--epsilon-delta Δε] \
[--workforce-decay] [--guf-inflow TEH]
python3 utils/eoh_cli.py simulate --periods 20 --epsilon 0.30 --epsilon-delta 0.02
# With workforce decay and GUF land-fee injection:
python3 utils/eoh_cli.py simulate --periods 20 --epsilon 0.30 --epsilon-delta 0.02 \
--workforce-decay --guf-inflow 50000.0
--workforce-decay — when set, workforce_fraction shrinks proportionally as ε rises each period (models labor displacement).
--guf-inflow TEH — inject a fixed GUF land-fee revenue (TEH) into the Trust each period.
sensitivity¶
Parameter and arc sensitivity sweeps.
python3 utils/eoh_cli.py sensitivity fiscal --parameter PARAM --values V1,V2,... [--epsilon ε]
python3 utils/eoh_cli.py sensitivity arc [--start ε] [--end ε] [--points N] [--format table|csv|json]
python3 utils/eoh_cli.py sensitivity delta [--epsilon ε] [--delta Δε]
guf — Land Use Fee Commands¶
Ground Use Fee calculations. See GUF Framework for the mathematical specification.
guf calculate¶
python3 utils/eoh_cli.py guf calculate \
--epsilon 0.40 \
--area-slu 3.5 \
--use-category residential_primary \
--location-value 0.629 \
[--format table|json]
Use categories: residential_primary, residential_secondary, agricultural_active, agricultural_fallow, commercial_retail, commercial_office, industrial_light, industrial_heavy, institutional, conservation.
guf trust¶
python3 utils/eoh_cli.py guf trust \
--revenues 1.5,2.3,0.8 \
[--subsidies 0.5] \
[--format table|json]
guf writedown¶
Compute modified GUF during an ecological write-down event (NLSA Eq. 29).
# Restoration pathway (default)
python3 utils/eoh_cli.py guf writedown \
--epsilon 0.40 --area-slu 3.5 --pathway restoration \
--services-reset-json '[{"label":"water","volume":0.4,"kappa_ref":1.65,"beta":0.8,"retained":0.3}]'
# Abandonment pathway
python3 utils/eoh_cli.py guf writedown \
--epsilon 0.40 --area-slu 3.5 --pathway abandonment \
--services-reset-json '[{"label":"water","volume":0.2,"kappa_ref":1.65,"beta":0.8,"retained":0.3}]' \
--services-lost-json '[{"label":"biodiversity","volume_lost":5.0,"kappa_ref":0.35,"beta":0.7}]'
Services JSON formats:
Reset services (--services-reset-json):
Lost services (--services-lost-json):
Options: --pathway restoration|abandonment, --amortization-years N (default 50).
guf rebuilding-surcharge¶
python3 utils/eoh_cli.py guf rebuilding-surcharge \
--epsilon 0.40 \
--services-json '[{"label":"biodiversity","volume_lost":5.0,"kappa_ref":0.35,"beta":0.7}]' \
[--amortization-years 50] \
[--format table|json]
guf accumulation-warning¶
python3 utils/eoh_cli.py guf accumulation-warning \
--unfulfilled 450000 \
--total 1200000 \
[--threshold 0.30] \
[--format table|json]
Warns when unfulfilled / total > threshold (default 0.30). Triggers accelerated ρ_s review and ecology fund priority.
guf inventory — Collective Land Inventory¶
Batch GUF operations over a collective's full parcel inventory. Parcel data is provided as a JSON file — a list of objects following the standard parcel schema.
guf inventory calculate¶
Compute aggregate GUF for a parcel inventory at a given ε.
python3 utils/eoh_cli.py guf inventory calculate \
--parcels parcels.json \
[--epsilon 0.40] \
[--median-income 350.0] \
[--format table|json]
guf inventory sweep¶
Sweep aggregate GUF across the ε arc.
python3 utils/eoh_cli.py guf inventory sweep \
--parcels parcels.json \
[--epsilon-start 0.0] \
[--epsilon-end 0.99] \
[--steps 20] \
[--format table|json]
guf inventory stress¶
Multi-period automation→levy→GUF stress test.
python3 utils/eoh_cli.py guf inventory stress \
--parcels parcels.json \
[--epsilon-start 0.20] \
[--epsilon-end 0.80] \
[--periods 20] \
[--population 1000000] \
[--format table|json]
Omit --parcels to use the default 1 000-parcel synthetic urban inventory.
Parcel JSON format (list of parcel dicts; only the three required fields needed for a minimal inventory):
[
{"area_slu": 3.5, "location_value": 0.72, "use_category": "residential_primary"},
{"area_slu": 5.0, "location_value": 0.85, "use_category": "commercial_retail",
"ecosystem_services": [{"label": "water", "volume": 0.4, "kappa_ref": 1.65, "beta": 0.8, "retained": 0.3}]}
]
See Land — Collective Inventory for the full parcel schema.
contestability — Contestability Invariant (§8)¶
Arc table, stress sweep, derived levy schedule, the §8.9 recalibrated arc, and the §8.7e membership-terms audit.
python3 utils/eoh_cli.py contestability arc [--regime increasing_returns|replicable] [--points N]
python3 utils/eoh_cli.py contestability stress [--points N]
python3 utils/eoh_cli.py contestability levy [--chi-target 1.0] [--levy-base capital_yield|machine_output]
python3 utils/eoh_cli.py contestability recal [--regime ...] [--points N] [--capital-output-ratio 4.0]
python3 utils/eoh_cli.py contestability audit [--terms-json PATH|-] [inline flags]
--levy-base machine_output uses the physically-consistent base
ε·total_EOH (the pipeline's own measure of automated production) instead of
the static ε·K·yield, which understates it ~12× at high ε (proposed §8.8 M3).
contestability recal¶
The proposed-§8.9/§8.9b recalibrated arc: the commons owns share φ(ε) of an
ε-consistent capital stock (τ = φ ≤ 1, dτ/dε ≥ 0 structural), and exit is
financed by own labor (low ε), commons underwriting (mid ε), or dividend
savings (high ε) — t_exit ≤ horizon replaces the retired flow/stock χ.
--phi-policy selects the doctrine: dilution (default, §8.9b charter
formation — the commons' share attaches to new capital at commissioning;
private capital is never sold down, so φ caps at ≈ 0.66 by ε = 0.99, marked
* in the table), target (§8.9a purchase model, regression anchor), or
escalated (dilution + the charter escalation clause — full generational
conversion via capital-estate escheat if observed concentration threatens
exit; never fires at canonical defaults, rows marked ! when active).
--estate-escheat sets the baseline capital-estate share (default 0.15 =
ESTATE_LEVY_FRACTION, the D5 doctrine extended); raise
--min-viable-population to stress the escalation trigger.
# The doctrine arc (dilution default)
python3 utils/eoh_cli.py contestability recal
# §8.9a purchase model for comparison
python3 utils/eoh_cli.py contestability recal --phi-policy target
# Force the escalation clause to fire (40× founding cohort)
python3 utils/eoh_cli.py contestability recal --phi-policy escalated \
--min-viable-population 200000
contestability formation¶
The §8.9c formation-feedback simulation: formation is financed or it does
not happen (private supply falls as the charter share rises), the commons
co-funds from net income per --priority (share-first holds the canonical
pace at the dividend's expense; dividend-first crawls and never completes),
and ε derives from the capital actually formed. --charter-share 0 is the
null anchor; --hurdle/--full-supply toward fiat-like returns quantify
the Condition III finding (zero interest makes the charter affordable:
s* = 0.50 vs ≈ 0.10 fiat-like).
# The doctrine run (share-first)
python3 utils/eoh_cli.py contestability formation
# The crawling counterfactual
python3 utils/eoh_cli.py contestability formation --priority dividend --years 120
# The fiat-world counterfactual (dividend driven to zero mid-arc)
python3 utils/eoh_cli.py contestability formation --hurdle 0.06 --full-supply 0.18
contestability audit¶
Checks proposed membership terms against the χ invariant (the code audits the
contract; it does not legislate it). Terms come from a JSON file, stdin (-),
or inline flags (--vesting-years, --admission-cost, --exit-notice-years,
--minimum-hours, --dividend-fraction); inline flags override JSON keys.
# Inline: an admission fee at high ε breaches the invariant
python3 utils/eoh_cli.py contestability audit --admission-cost 800 --epsilon 0.9
# From a terms file
python3 utils/eoh_cli.py contestability audit --terms-json terms.json --epsilon 0.4
# §8.8 closure flags: same admission fee, but a funded commons finances exit
python3 utils/eoh_cli.py contestability audit --admission-cost 800 --epsilon 0.9 \
--commons-balance 1e10 --commons-dividend --underwriting-policy
Terms JSON format (all fields optional; absent fields keep canonical defaults):
{
"vesting_years": 5.0,
"admission_cost_teh": 250.0,
"exit_notice_years": 0.5,
"minimum_hours_annual": 400.0,
"dividend_policy_fraction": 1.0
}
coasean — Collective Federation (§§6–7, §8.7)¶
Research-tier federation mechanics. --format table|json goes before the subcommand.
python3 utils/eoh_cli.py coasean n1-check # N=1 regression anchor
python3 utils/eoh_cli.py coasean count # emergent N(ε) across the arc
python3 utils/eoh_cli.py coasean federation --epsilon 0.4 # per-collective snapshot
python3 utils/eoh_cli.py coasean federation --frame us --split us_states # the US frame by state
python3 utils/eoh_cli.py coasean simulate --periods 10 # multi-period arc
coasean federation on a frame¶
Without a frame, federation divides the reference economy into N(ε) equal
collectives and charges no land fee. On --frame / --frame-file it divides
the FRAME instead. Each collective runs the same path as scenario run
collective on that frame: its land, its labour supply, and the per-parcel land
fee, capped at what its own mint can pay. A total row and the whole frame run
as one collective are printed beside the collectives.
--split NAME|PATH names how the frame divides. us_states ships, holding the
48 states and DC. Without --split, the frame divides into N(ε) equal shares,
or --n of them. A split file is JSON. Each entry in its collectives list
gives an id, an optional label, and positive population,
land_hectares and parcel_count. Those three are WEIGHTS: each collective
gets its share of the frame's totals, and its population share of the frame's
capital and Trust. An entry may also state its own age_fractions, which
replace the frame's mix; us_states does, from Census 2025 single-year ages.
Every other input (labour capacity, stock age, ε) is the frame's. Because the fee cap applies collective by collective, the
collected fees need not add up to the whole frame's.
coasean simulate flags¶
| Flag | Effect |
|---|---|
--dynamics |
Phase 3 Trust/capital evolution (adds T, τ, piketty columns) |
--g-priv F |
private capital growth per period (with --dynamics) |
--levy-rate F |
common-fund levy on automated output (with --dynamics) |
--commons |
Phase 4 two-tier commons: escheat, tithe, per-collective χ (adds commons, escheat, χ_marg_min, χ_status columns) |
--commons-tithe F |
levy fraction routed to the federation commons (default 0.03) |
--regime R |
K_entry regime for per-collective χ |
--commons-dividend |
§8.8 M1: commons pays a universal unvested dividend that feeds χ (adds entry_cap, exit_fin semantics) |
--commons-start F |
initial commons balance in TEH (seed; commons_seed_required() ≈ 1.8e7 at defaults) |
# The full two-tier arc: consolidation escheat, tithe, and the χ invariant
python3 utils/eoh_cli.py coasean simulate --periods 10 --dynamics --commons --levy-rate 0.3
# §8.8 closure: seeded commons + universal dividend → exit financeable across the arc
python3 utils/eoh_cli.py coasean simulate --periods 21 --epsilon-start 0.0 --dynamics \
--g-priv 0.02 --levy-rate 0.2 --commons --commons-dividend --commons-start 1.8e7