Scenario Lab#

The scenario lab (means.lab) is the shared application layer over means.planning. It owns scenario validation, named hypotheses, variant generation, sensitivity ranking, and stable presentation models. The CLI (means-plan), TUI (means-tui), and web UI (means-web) all consume one typed API – no surface-specific financial calculation forks exist.

Core concepts#

Hypotheses#

A hypothesis is a named question over the scenario with at least two named alternatives. Each alternative carries typed overrides targeting fields from the finite registry:

  • starting_cash – the opening cash balance

  • reserve_floor – the minimum cash floor

  • extra_debt_payment – the monthly extra debt payment

  • allocation_day – the monthly extra-allocation date

All alternative names within a hypothesis must be unique.

Variants#

The lab evaluates the Cartesian product of hypothesis alternatives. Variant expansion fails closed above a documented bound (MAX_VARIANTS = 64).

from decimal import Decimal
from means.lab import (
    Alternative,
    Hypothesis,
    HypothesisTarget,
    LabRequest,
    OverrideTarget,
    ScenarioLab,
)

request = LabRequest(
    scenario=scenario,
    hypotheses=[
        Hypothesis(
            name='Starting cash',
            alternatives=[
                Alternative(
                    name='low',
                    targets=[
                        HypothesisTarget(
                            field=OverrideTarget.STARTING_CASH,
                            value=Decimal('3000.00'),
                        ),
                    ],
                ),
                Alternative(
                    name='high',
                    targets=[
                        HypothesisTarget(
                            field=OverrideTarget.STARTING_CASH,
                            value=Decimal('8000.00'),
                        ),
                    ],
                ),
            ],
        ),
    ],
)

result = ScenarioLab().evaluate(request)

Sensitivity ranking#

Sensitivity is descriptive, not causal. For each hypothesis and metric, the lab measures the spread observed across the evaluated variants and reports the range with its low and high variant labels. This does not prove that a hypothesis causes the observed difference.

Shared result model#

The typed EvaluationResult returned by ScenarioLab().evaluate(...) is the single presentation model consumed by every surface (CLI, TUI, WUI). Results serialize only application-layer types – never private data.

Fictional example#

This example uses entirely fictional data:

A scenario-lab document wraps the planning scenario under a scenario: key and adds optional hypotheses:

scenario:
  name: Fictional demo scenario
  as_of: 2026-01-01
  through: 2026-06-30
  starting_cash: '5000.00'
  reserve_floor: '500.00'
  flows:
    - uid: income
      name: Income
      category: salary
      kind: inflow
      amount: '3000.00'
      start: 2026-01-01
      frequency: monthly
  debts:
    - uid: card
      name: Card
      balance: '2000.00'
      annual_rate: '0.18'
      minimum_payment: '150.00'
      due_day: 5
  extra_debt_payment: '200.00'
  allocation_day: 10
hypotheses:
  - name: Reserve policy
    alternatives:
      - name: Conservative reserve
        targets:
          - field: reserve_floor
            value: '1000.00'
      - name: Lean reserve
        targets:
          - field: reserve_floor
            value: '250.00'

Privacy and safety#

  • All computation is local; no financial data is sent remotely.

  • Neither the TUI nor the WUI mutates a Ledger.

  • The WUI binds to loopback (127.0.0.1) by default.

  • The WUI parses no arbitrary paths from browser input.

  • Both interfaces label scenario math as hypotheses, not predictions or financial advice.

  • Optional UI dependencies do not enlarge the base installation.