Spaces:
Running
Running
| # Blueprint Rewrite β Migration Notes | |
| ## What changed conceptually | |
| Old: LLM does a thin extraction -> keyword router picks a scenario family -> | |
| Python templates with hardcoded value lists fill the gaps -> specialized | |
| generators for the verticals we've hand-tuned. | |
| New: one rich LLM call authors a complete **DemoBlueprint** (all semantics: | |
| real domain nouns, distributions, formulas, seasonality, and 3-5 **planted | |
| insights** with the exact Spotter questions that reveal them) -> one generic | |
| deterministic **BlueprintEngine** executes any blueprint -> a **validator** | |
| proves each planted insight is demo-visible in the actual rows, and a cheap | |
| boost-and-regenerate loop fixes weak ones at the contract level. | |
| The LLM decides what the data means; deterministic code decides what the rows | |
| are. No vertical-specific code anywhere downstream of the blueprint. | |
| ## New files | |
| | File | Role | | |
| |---|---| | |
| | `demoprep_app/scenario/blueprint.py` | DemoBlueprint dataclasses + `problems()` validation (repair messages are written for the LLM) | | |
| | `demoprep_app/scenario/blueprint_author.py` | The one LLM call. The user's request is quoted verbatim as highest authority; few-shot examples replace scenario families. Up to 2 repair rounds. | | |
| | `demoprep_app/scenario/directives.py` | Deterministic extraction + enforcement of explicit user schema instructions (named tables, prohibitions). Direct fix for the McKesson routing failure. | | |
| | `demoprep_app/dataset/engine.py` | The only generator. Deterministic given (blueprint, seed). Also decides date-dimension-vs-inline-date per blueprint, resolving the open date-modeling question. | | |
| | `demoprep_app/dataset/validator.py` | Integrity + formula + planted-insight checks over the in-memory bundle | | |
| | `demoprep_app/pipeline/build_demo.py` | THE pipeline (there is exactly one): author -> generate -> validate -> boost loop -> DDL. Canonical entry `build_demo()`; `dataset_first.py` remains only as a deprecated import shim during cutover. | | |
| | `SINGLE_PIPELINE.md` | Surgery guide for chat_interface.py: delete the `data_generation_mode`/`DEMOPREP_DATASET_FIRST` fork (which currently **defaults to legacy**), the silent "falling back to DDL-first" branch, the legacy LLM-DDL stage, and the LegitData population path. | | |
| | `tests/test_blueprint_pipeline.py` | LLM-free smoke test (run: `PYTHONPATH=. python tests/test_blueprint_pipeline.py`) | | |
| | `tests/test_mckesson_regression.py` | Replays the real McKesson failure: extracts directives from the actual prompts, rejects the exact FACILITIES/SERVICE_LINES output the old app produced, and builds the correct 6-table / 2-fact demo. | | |
| ## Delete (no longer imported) | |
| - `demoprep_app/scenario/selector.py` β keyword routing | |
| - `demoprep_app/scenario/extractor.py` β thin extraction | |
| - `demoprep_app/scenario/families.py` β templates-as-code (their knowledge now | |
| lives as few-shot JSON in `blueprint_author.py`; port any families you find | |
| valuable as additional compact examples) | |
| - `demoprep_app/dataset/generators/` β all of it: `base.py`, `router.py`, | |
| `retail_sales.py`, `saas_sales.py`, `template_generator.py` | |
| ## Untouched | |
| - `demoprep_app/dataset/contracts.py` (DatasetBundle/Table/Column) | |
| - `demoprep_app/ddl/` DatasetDdlCompiler | |
| - `demoprep_app/integrations/snowflake.py` `populate_dataset_bundle` | |
| - `chat_interface.py` call site (signature preserved; `use_llm_contract` kept | |
| as a no-op arg) | |
| Two files in this package are **test stubs only** β replace with your real | |
| modules when dropping in: `demoprep_app/scenario/contract.py` and | |
| `demoprep_app/ddl/__init__.py`. If your real `ScenarioContract` has different | |
| field names, adjust `_compat_scenario()` in `engine.py` (one function, ~30 | |
| lines β the only place the two worlds touch). | |
| ## The McKesson failure, specifically | |
| The 2026-07 incident (custom prompt naming 6 exact tables -> keyword-routed to | |
| the healthcare_operations family -> FACILITIES / SERVICE_LINES / PAYERS / | |
| REGIONS / HEALTHCARE_OPERATIONS) is now impossible three ways: | |
| 1. `selector.py` and `families.py` are deleted β there is no keyword router | |
| and no hardcoded table set to route into. | |
| 2. The author prompt quotes the user's request verbatim as the highest | |
| authority, with an explicit warning against modeling the industry's | |
| generic operations instead of the company's actual business. | |
| 3. `directives.py` extracts named tables (DIM_*/FACT_* tokens) and | |
| prohibitions ("do not create facilities...", "not a hospital operations | |
| demo") from the user's own words and enforces them deterministically. | |
| Violations feed the LLM repair loop; any that survive retries abort the | |
| build with `USER DIRECTIVE VIOLATED` β the wrong story can never | |
| silently ship. `chat_interface.py` should pass the raw custom prompt as | |
| `user_request=` (falls back to `use_case` otherwise). | |
| Blueprints also now support **1-3 fact tables over shared dimensions** | |
| (`facts: [FactSpec]`), because real custom specs like McKesson's have two. | |
| Measure names must be unique across facts; insights resolve to the fact | |
| owning their measure; each fact can name its date column (e.g. MONTH_DATE). | |
| ## Behavior changes to be aware of | |
| 1. **Fails loudly.** No silent fallback to templates. If the LLM can't produce | |
| a valid blueprint after repair rounds, the build raises with the validation | |
| report. A template demo is worse than a clear error you can retry. | |
| 2. **Planted insights flow downstream.** `bundle.scenario.metadata["planted_insights"]` | |
| carries id/headline/spotter_question/expected_finding β wire these into the | |
| liveboard question generator and Spotter Viz story so the demo narrative and | |
| the data are guaranteed to agree. That's the Demo to Win payoff. | |
| 3. **Date dimension is now a per-scenario LLM decision** (blueprint field | |
| `date.include_date_dimension`, forced true when `fiscal_or_custom_calendar` | |
| is set) instead of always-emitted. Matches the design guidance in the | |
| architecture doc. | |
| 4. **`performance` and insight magnitude compound.** A store with | |
| performance 0.8 that is also a 0.75 laggard insight lands around 0.6x. | |
| The validator only requires half the promised effect to realize, so this | |
| is safe, but the effect can be stronger than the headline claims. If that | |
| bothers you, have the author prompt forbid overlapping the two. | |
| 5. **Determinism.** Seed derives from `company_url|use_case`, so rebuilding | |
| the same demo produces the same data β good for the e2e quality harness. | |
| ## Suggested follow-ups (not included) | |
| - Port your best `families.py` entries into 2-3 more few-shot examples. | |
| - Feed `planted_insights` into `liveboard_creator.py` question generation. | |
| - e2e harness: assert `build.validation.passed` and surface `build.warnings`. | |