1 · What is a KPI unit worth?

Every dollar recommendation in the framework flows through one resolver, kpi_to_dollars, and its rule is absolute: a KPI unit is never silently worth one dollar. The valuation is a declared statement (revenue kind with a gross margin, or unit kind with margin × price), resolved with provenance from an explicit override, the model spec, or the project's economics preference—in that order. When nothing resolves, the result says is_dollar=False and every downstream dollar figure is suppressed rather than invented.

from mmm_framework.finance.valuation import kpi_to_dollars

resolved = kpi_to_dollars(
    override={"kind": "units", "gross_margin": 0.6, "price": 10.0}
)
resolved.value_per_kpi   # 6.0 — margin x price, with provenance recorded
kpi_to_dollars().is_dollar   # False — nothing resolved, nothing invented

Two guardrails exist because each absorbed a real failure. The gross margin is bounded to (0, 1]: an earlier resolver accepted gross_margin=40 (a user meaning 40%) and multiplied every profit figure by forty. And a KPI declared kind="other" (sessions, awareness points) is a resolved answer—genuinely not convertible—so the resolver stops there instead of falling through to a lower-precedence setting that would contradict the explicit choice. Both rules are pinned in tests/finance/test_valuation.py.

2 · Forecast under a plan

forecast_under_plan produces the KPI forecast a plan is judged against. Its interval is predictive (observation noise included), because that is the interval a realized season can land inside or outside of. Two design rules matter more than the point estimate:

  • Caveats lead. A forecast result that lost its caveats refuses to render its headline. The caveats are not boilerplate: the model states when the plan pushes channels beyond the spend range it was fitted on (saturation extrapolation), when the trend is being extrapolated forward, and when the fit was approximate—in which case the interval is disclosed as uncalibrated rather than dressed up.
  • Controls are a planning assumption. When the model has control variables, their future values are required. There is no defensible default for next quarter's price or distribution, so the forecast refuses rather than assuming one.

The per-period posterior draws ride along with every forecast, because a window-total interval cannot be recovered from per-period bounds—summing them assumes perfect correlation and overstates the band. The draws are what the plan of record grades itself against later. (tests/test_forecast.py, technical-docs/forward-forecast.md.)

3 · The plan of record

Committing a plan writes an append-only, hash-chained version. A committed version is immutable—editing it would make every variance already computed against it retroactively wrong while the audit trail still looked intact, so the store's update path raises instead of updating. The commitment gates check that the version carries everything needed to regenerate its number: the run, the spec hash, the dataset fingerprint, the saved model, the normalized per-period plan and the seed.

That reproducibility is the point: a stored forecast nobody can reproduce is a screenshot wearing a commitment's clothes. reproduce_committed_plan reloads the model from the recorded provenance, rebuilds the panel from the saved spec, re-runs the forecast with the recorded plan and seed, and requires agreement to 1e-9. A changed dataset is a refusal, not a mismatch report—"the data moved" and "the model drifted" are different statements, and conflating them blames the model for a moved file. (tests/test_plan_of_record.py; the end-to-end roundtrip is pinned in tests/test_variance_bridge.py.)

4 · Payback horizons

channel_payback reports when each channel's effect lands: the per-draw lag at which the fitted carryover crosses 50% (t50) and 90% (t90) of its total effect, with credible intervals. It is a response-timing statement, not a cash break-even—and it rests on the model's least-identified parameter, so every number travels with its disclosures:

  • the kernel mass beyond the configured window (truncation makes horizons read short, and the bias is quantified per channel);
  • whether the carryover parameters actually learned from the data or still sit on their prior (a prior-dominated horizon is a restatement of the prior, and it is labelled as one);
  • an autocorrelation gate that flags a misspecified carryover window.

Model families with no single kernel to read a horizon from—extension models, structural models with AR(1) mediators, dual-stock brand models—are refused by name. The cash-flavored break-even wrapper needs a valuation and refuses without one. (tests/test_planning_payback.py; walkthrough in nbs/demos/payback_horizon.ipynb.)

5 · Price & promo levers

Media dollars and promo depth are different cost spaces. The decision-arm layer unifies them with per-arm cost bases, so a joint optimization can trade a media dollar against a point of discount depth on a real profit objective. Its refusals are the product:

  • Promo ROI refuses flag promos and unknown units. A 0/1 promo flag has no dollar cost basis, so "promo ROI" per flag-week would be a fabricated per-dollar number. The arm builder refuses and says what a computable basis would need.
  • The price what-if refuses to recommend a price. Price is usually endogenous—cut because demand is soft—so the surface answers "what does the model expect at price X" and declines to rank prices. An endogeneity screen (using lagged demand, because contemporaneous response is not endogeneity evidence) flags the channels where the concern is live.

The joint solve is graded against planted truth: on the promo_and_media synthetic world, the optimizer's recommended depth lands within the planted profit optimum on 10 of 10 seeds (tests/test_decision_arms.py; walkthrough in nbs/demos/promo_depth_optimization.ipynb). Model-side lever mechanics live in the Modeling Guide and technical-docs/price-promotion-levers.md.

6 · Variance to plan

A season later, the CFO asks why the miss. Without refitting the model, exactly two buckets are identifiable, and the bridge ships exactly those: delivery variance—the committed posterior's own pricing of the spend divergence, computed as a paired counterfactual with the recorded seed—and an unexplained remainder, labelled for what it mixes (baseline movement, competitor action, data error, model error, noise) and never attributed.

The tempting third bucket—refit on the realized season and call the difference "effectiveness variance"—is refused with the reason stated: that subtraction mixes more data, a different training window, any spec changes and Monte Carlo noise, and labelling it manufactures a causal claim nobody measured. What can be said (what changed between the runs) is attached in the refusal's place.

  • The bridge closes exactly: rows sum to actual − committed to 1e-9 by construction, and a model that cannot reproduce the committed snapshot is refused outright.
  • The committed-interval verdict leads: a miss inside the band that was committed to is the uncertainty that was signed, not a story owed.
  • Human adjustments (gross-to-net, returns) enter as SUPPLIED lines: a required source note, no invented interval, total-only—a supplied line rescaling a channel would produce a net-scaled ROI the model never estimated.

In the clean synthetic world where the plan is the true future spend rescaled (TV at 1.3×, Search at 0.7×), the bridge's delivery rows carry the right signs and the paired-draw interval covers the world's own response_fn truth (tests/test_variance_bridge.py; walkthrough in nbs/demos/variance_to_plan.ipynb).

The refusal index

Collected in one place, because they are the design. Each is a hard error or a stated refusal on the surface, never a silent default.

SurfaceRefuses whenInstead of
kpi_to_dollars consumers no valuation resolves, or the KPI kind is not convertible assuming 1 KPI unit = $1
Fund-to-breakeven allocation (mode="free") value_per_kpi is unresolved funding every channel to a fabricated breakeven line
Budget curves a channel is efficiency-measured (impressions/clicks, no cost basis) optimizing dollars against a non-dollar axis
forecast_under_plan the model has controls and no future values were supplied assuming next quarter's price
Plan-of-record commit provenance is incomplete (no run, spec hash, fingerprint, or model) committing a number nobody can regenerate
Reproduction the dataset fingerprint changed since the commit "verifying" against different data
Payback the model family has no single carryover kernel reading a horizon that does not exist
Promo ROI the promo is a flag or its units carry no cost basis a fabricated per-dollar number
Price what-if asked to recommend a price ranking prices on an endogenous coefficient
Variance bridge a refit split is requested; actuals or delivery do not cover the committed window; the model cannot reproduce the snapshot an "effectiveness" bucket, or a bridge over fabricated inputs

The engineering rationale behind each lives in the technical-docs/ specs: kpi-valuation.md, forward-forecast.md, plan-of-record.md, payback-and-carryover.md, lever-optimization.md, variance-to-plan.md.