fix base costs and import backstage in ctm notebook

This commit is contained in:
r
2026-07-08 08:25:31 -04:00
parent d790afbc7c
commit b5af65891c
6 changed files with 2953 additions and 2687 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -106,3 +106,10 @@ def test_case_flows_and_kpis():
inc2 = {y: -1.0 for y in a4.YEARS} inc2 = {y: -1.0 for y in a4.YEARS}
net2 = {y: benefits[y] + 1.0 for y in a4.YEARS} net2 = {y: benefits[y] + 1.0 for y in a4.YEARS}
assert a4.case_kpis(inc2, net2)["roi"] is None assert a4.case_kpis(inc2, net2)["roi"] is None
def test_contracted_overlays_verbatim():
assert a4.tco("ccaas_annual") == 3_200_000 # signed contract
assert a4.TCO_VERBATIM["ccaas_annual"] == 4_300_000 # deck record intact
assert a4.tco("current_annual") == a4.TCO_VERBATIM["current_annual"]
assert a4.licence_costs_by_year(12, a4.tco("ccaas_annual"))[2027] == 3_200_000
@@ -0,0 +1,15 @@
"""Stage/backstage detection — Mercury kernels carry MERCURY_CONFIG_DIR."""
from tokencalc import staging
def test_backstage_prints_only_off_stage(monkeypatch, capsys):
monkeypatch.delenv("MERCURY_CONFIG_DIR", raising=False)
assert not staging.on_stage()
staging.backstage("visible")
assert capsys.readouterr().out == "visible\n"
monkeypatch.setenv("MERCURY_CONFIG_DIR", "/tmp/app")
assert staging.on_stage()
staging.backstage("hidden")
assert capsys.readouterr().out == ""
@@ -99,6 +99,19 @@ TCO_VERBATIM: dict[str, float] = {
"npv_discount_rate": 0.135, # deck's benefit-NPV rate "npv_discount_rate": 0.135, # deck's benefit-NPV rate
} }
#: Actual contracted values where they differ from the deck — 🟢
#: contractual. Layered over TCO_VERBATIM, which stays the untouched
#: record of what Genesys pitched (the anchor CTM can follow);
#: presentation reads through :func:`tco`.
TCO_CONTRACTED: dict[str, float] = {
"ccaas_annual": 3_200_000, # signed licence run-rate (deck pitched $4.3M/yr)
}
def tco(key: str) -> float:
"""Contracted value where one exists, else the deck's verbatim anchor."""
return TCO_CONTRACTED.get(key, TCO_VERBATIM[key])
#: Genesys/Broadreach deployment schedule (slides 17-21), months from #: Genesys/Broadreach deployment schedule (slides 17-21), months from
#: Jan 2026 inclusive. Benefits realize IMPL + 3 months. #: Jan 2026 inclusive. Benefits realize IMPL + 3 months.
IMPL_MONTH = {"NA": 18, "ANZ": 21, "EMEA": 24, "ASIA": 27} IMPL_MONTH = {"NA": 18, "ANZ": 21, "EMEA": 24, "ASIA": 27}
@@ -0,0 +1,29 @@
"""
Stage vs backstage — is this notebook render stakeholder-facing?
The Mercury CLI (``mercury --working-dir …``) exports ``MERCURY_CONFIG_DIR``
into the server process so the widget library can locate ``config.toml``
(see ``mercury/config.py``); every kernel that server spawns inherits it.
JupyterLab and nbconvert kernels don't have it. That makes the variable a
reliable signal for "the audience is looking" (the stage) versus an
analyst session or a headless export run (backstage).
Diagnostics routed through :func:`backstage` stay visible in JupyterLab
and land in the nbconvert exports (where the machine-readable appendix
must appear for LLM consumption) but never render in the Mercury app.
"""
from __future__ import annotations
import os
def on_stage() -> bool:
"""True when running under the Mercury app (stakeholder-facing)."""
return os.getenv("MERCURY_CONFIG_DIR") is not None
def backstage(*args, **kwargs) -> None:
"""``print`` that renders only backstage (JupyterLab, nbconvert)."""
if not on_stage():
print(*args, **kwargs)