BusinessReport ============== ``BusinessReport`` wraps any fitted diff-diff result object and produces stakeholder-ready output: - ``summary()`` — a short paragraph block suitable for an email or Slack. - ``full_report()`` — a structured multi-section markdown report. - ``to_dict()`` — a stable AI-legible structured schema (single source of truth; prose renders from this dict). By default, BusinessReport constructs an internal ``DiagnosticReport`` to surface pre-trends, sensitivity, and other validity checks as part of the narrative. Pass ``auto_diagnostics=False`` to skip this, or ``diagnostics=`` to supply an explicit one. Pre-computed diagnostics can be forwarded directly to the auto- constructed ``DiagnosticReport`` via ``precomputed={'parallel_trends': ...}``, ``precomputed={'sensitivity': ...}``, ``precomputed={'pretrends_power': ...}``, or ``precomputed={'bacon': ...}`` — same keys as ``DiagnosticReport(precomputed=...)``. DR validates keys and rejects estimator-incompatible entries. Data-dependent checks (2x2 parallel trends on simple DiD, Goodman-Bacon decomposition on staggered estimators, the EfficientDiD Hausman PT-All vs PT-Post pretest) require the raw panel + column names. Pass ``data``, ``outcome``, ``treatment``, ``unit``, ``time``, and/or ``first_treat`` to ``BusinessReport`` and they are forwarded to the auto-constructed ``DiagnosticReport``. Without these kwargs, those specific checks are skipped with an explicit reason while the rest of the report still renders. For survey-weighted fits (any result carrying ``survey_metadata``) pass the original ``SurveyDesign`` via ``survey_design=``. It is threaded through to ``bacon_decompose`` for a fit-faithful Goodman-Bacon replay. When ``survey_metadata`` is set but ``survey_design`` is not supplied, Bacon is skipped with an explicit reason so the report never emits an unweighted decomposition for a design that differs from the estimate. The simple 2x2 parallel-trends helper has no survey-aware variant and is skipped unconditionally on a survey-backed ``DiDResults`` regardless of ``survey_design``; supply ``precomputed={'parallel_trends': ...}`` with a survey-aware pretest to opt in. Methodology deviations (no traffic-light gates, pre-trends verdict thresholds, power-aware phrasing, unit-translation policy, schema stability) are documented in `docs/methodology/REPORTING.md `_. The schema carries a top-level ``target_parameter`` block (experimental) naming what the headline scalar represents per estimator — simple ATT, event-study average, DID_M, DID_1, cost-benefit delta, dose-response aggregate, factor-model-adjusted ATT, etc. For the dCDH dynamic branch with ``trends_linear=True`` and ``L_max>=2``, the scalar is intentionally NaN and ``aggregation`` is ``"no_scalar_headline"`` with ``headline_attribute`` set to ``None``. Agents should dispatch on this case and inspect the headline ``reason`` field, which distinguishes the populated-surface subcase (per-horizon table available on ``linear_trends_effects``) from the empty-surface subcase (no horizons survived estimation; re-fit with a larger ``L_max`` or with ``trends_linear=False``). See the "Target parameter" section of `docs/methodology/REPORTING.md `_ for the full per-estimator dispatch table and schema shape. Example ------- .. code-block:: python from diff_diff import CallawaySantAnna, BusinessReport cs = CallawaySantAnna(base_period="universal").fit( df, outcome="revenue", unit="store", time="period", first_treat="first_treat", aggregate="event_study", ) report = BusinessReport( cs, outcome_label="Revenue per store", outcome_unit="$", business_question="Did the loyalty program lift revenue?", treatment_label="the loyalty program", # Optional: panel + column names so auto diagnostics can run the # data-dependent checks (2x2 PT, Goodman-Bacon, EfficientDiD # Hausman). Without these the auto path still runs and just # skips those checks. data=df, outcome="revenue", unit="store", time="period", first_treat="first_treat", ) print(report.summary()) API --- .. autoclass:: diff_diff.BusinessReport :no-index: :members: :show-inheritance: .. autoclass:: diff_diff.BusinessContext :no-index: :members: :show-inheritance: .. autodata:: diff_diff.BUSINESS_REPORT_SCHEMA_VERSION