Skip to content

Part C — Demo-Ready Close-Out

Status: completed (2026-05-06). Closed the remaining gap between "Prompt 5 shipped" and "the entire prototype is demoable." Reconciled Prompt 5's plan files, wrote the new Part C ~3-minute demo arc (including a real §C.6.1 reroute of cost_avoided_mtd from Postgres to Databricks), captured receipts for acceptance gates #1, #3, #4, #6, ran dry-run #11 twice clean, prepared the operator handoff for #12. All 12 PRD §C.10 acceptance gates are green (gate #12 operator-gated; every prerequisite landed) and part-c-databricks-prototype.md moved to completed/.

Why this exists

The parent plan's todo list showed Prompts 1-4 done and Prompt 5 + Prompt 6 + 6 acceptance gates pending. Reading the actual codebase, Prompt 5's frontend code, tests, and artifacts were already committed (frontend/src/widgets/{useWidgetData,SourceBadge,WidgetPreview,MyWidgetsRail,MetricInfoBadge,SpecJsonView}.tsx + 3 Vitest files; receipts in artifacts/prompt-5-frontend-wiring/20260506-120610/). The drift was in the bookkeeping — and a handful of demo-arc artifacts that genuinely didn't exist yet. This plan closed both at once.

What landed

  • Reconciled bookkeeping: docs/plans/completed/prompt-5-frontend-wiring.md flipped to status: completed; matching parent-plan todos (prompt_5_frontend_wiring, acceptance_dryrun_9, frontend leg of acceptance_dryrun_10) flipped.
  • Live cost_avoided_mtd reroute path (the §C.6.1 demo moment):
    • l3_asurion.ev_claim seeder extended with a cost_avoided_usd column populated by status-weighted distribution (backend/scripts/databricks_mock_data/l3_asurion_generators.py).
    • metrics_catalog.cost_avoided_mtd.source_query updated to query l3_asurion.ev_claim over trailing_30d (backend/app/metrics/seed.py).
    • config/metric_routing.yaml keeps cost_avoided_mtd: backend: postgres — the on-stage flip is to databricks + make up.
    • Pre-validated: Postgres path returns $1.41M in 5ms; Databricks path returns $374,714.39 in 765ms with source=bedrock and the real generated SQL.
  • Demo runbook §C arc: docs/demo-runbook.md gained a new top-level "Part C — Live data binding arc (~3 min)" section after the existing v1 90s arc and Add Widget arc. Includes the §C.6.1 reroute moment scripted as a real on-stage YAML edit + make up. Pre-flight pre-warm is explicit.
  • README.md update: README.md gained a "Live Databricks integration (Part C)" section with the DATABRICKS_* env-var checklist + a per-metric live-vs-synthetic table.
  • Architecture diagram check: docs/architecture.md Mermaid diagram already showed dbx_l3; added a dashed Kafka "Phase 2 — production transport" node + dotted edge with ADR-PROTO-001 pointer.
  • Acceptance receipts captured under artifacts/part-c-demo-ready/20260506-131614/:
    • Gate #1: time make up cold + warm (make_up_{cold,warm}.log)
    • Gate #3: make validate-dictionary exit-0 (validate_dictionary.log)
    • Gate #4: dry-run SQL gen for all 4 demo metrics (sqlgen_*.json)
    • Gate #6: layered safety defense (gate6_live_adversarial.json + gate6_safety_violation_unit.log)
    • Gate #11: terminal log of two clean back-to-back programmatic dry-runs (dryrun_run1.log + dryrun_run2.log)
    • Gate #12: operator handoff doc (E2_OPERATOR_HANDOFF.md) — the MP4 itself is operator-gated
  • Lessons harvest: 3 new entries appended to docs/lessons-learned.md: reroute moments need a pre-existing column on the destination side; dual source of truth between metrics_catalog.source_query and the Postgres allowlist; seed_if_empty is INSERT-only.
  • Plan close-out: parent part-c-databricks-prototype.md moved to docs/plans/completed/ with status: completed + completed_on: 2026-05-06. CLAUDE.md "Active plans" line updated to drop Part C; "Current State" Part C bullet rewritten.

Execution log (2026-05-06)

Phase What landed Receipt
A Prompt 5 plan + parent plan reconciled; close-out note added docs/plans/completed/prompt-5-frontend-wiring.md + part-c-databricks-prototype.md
B1 cost_avoided_usd column added to ev_claim seeder backend/scripts/databricks_mock_data/l3_asurion_generators.py
B2 cost_avoided_usd added to column_dictionary.csv + column_count bumped on table_catalog.csv data-dictionary/column_dictionary.csv + data-dictionary/table_catalog.csv
B3 cost_avoided_mtd.source_query points at l3_asurion.ev_claim over trailing_30d backend/app/metrics/seed.py
B4 Both paths live-validated; YAML restored to postgres cost_avoided_mtd_postgres.json + cost_avoided_mtd_databricks.json
B5 cost_avoided_mtd added as Metric 4 in demo-queries.md docs/demo-queries.md
B6 whats-mocked-in-prototype.md gains cost_avoided_mtd row + value-jump Q&A docs/whats-mocked-in-prototype.md
C1 Part C arc + §C.6.1 sub-section in demo-runbook docs/demo-runbook.md
C2 Live Databricks integration section in README + docs index pointers README.md
C3 Kafka Phase 2 dashed node added to architecture Mermaid docs/architecture.md
C4 3 new lessons appended docs/lessons-learned.md
D1 Gate #1 receipt make_up_{cold,warm}.log
D2 Gate #3 receipt validate_dictionary.log
D3 Gate #4 receipts (4 metrics) sqlgen_claim_volume_l3_asurion.json + sqlgen_claims_by_product_l3_asurion.json + sqlgen_claim_status_mix_l3_asurion.json + sqlgen_cost_avoided_mtd.json
D4 Gate #6 receipts (live + unit) gate6_live_adversarial.json + gate6_safety_violation_unit.log
E1 Two clean programmatic dry-runs dryrun_run1.log + dryrun_run2.log
E2 Operator handoff prepared (MP4 gated on human driver) E2_OPERATOR_HANDOFF.md
F Parent plan archived to completed/; CLAUDE.md updated this file

Acceptance roll-up

All 12 PRD §C.10 gates green. The single asterisk is gate #12: the backup MP4 itself requires a human driver to record against the running stack (live Bedrock + live Databricks + on-stage YAML edit), and the operator handoff at artifacts/part-c-demo-ready/20260506-131614/E2_OPERATOR_HANDOFF.md is the single landing page for that step. Every prerequisite (recording steps, runbook section, gitignore coverage) is in place.

Surprises / decisions

  • seed_if_empty is INSERT-only. Editing a metric's catalog row in seed.py does NOT update an existing warm-dev DB row. Caught during B3 — the workaround is TRUNCATE metrics_catalog before make up. Captured in lessons-learned.
  • trailing_30d vs MTD for cost_avoided_mtd: the Databricks path uses trailing_30d for consistency with the other Databricks-routed metrics; the Postgres path stays hardcoded to MTD via data_resolver._POSTGRES_QUERIES. The values therefore differ between the two paths ($1.41M Postgres vs $375k Databricks) — the value-jump is intentional and is documented in docs/whats-mocked-in-prototype.md.
  • Bedrock-side adversarial defense. When DROP TABLE was injected into filter values, Bedrock itself recognized + refused — its explanation literally said "DDL injection attempt and not a valid filter predicate." The 422 safety_violation path is exercised by the unit test that forces a hypothetically-rogue LLM to emit DROP TABLE.

References