Validation report
Three test suites cover the platform end-to-end. The industry suite verifies the platform can solve canonical ML problems (churn, hospitalization, fraud, …) end-to-end on multi-table data. The deployment suite verifies the second leg of the ML lifecycle — scheduled re-scoring stays correct under drift, idempotency, and operational failure modes. The regression suite locks in fixes to specific bugs we've shipped — every fix gets a synthetic case that captures the failure mode so it can't quietly come back.
New to this page? Read the methodology first.
At a glance
- Industry suite: 8/8 problems passing on their latest run
- Deployment suite: 21/21 failure modes guarded on their latest run
- Canonical suite: 3/3 absolute-truth claims locked on their latest run
- Regression suite: 19/21 cases passing on their latest run (coverage: 21/112 matrix cells, 18%) — 1 failing, 1 not yet run
- 171 total runs recorded across both suites
- Last refreshed:
2026-08-24T17:43:52
Industry suite
Each row is a canonical ML problem an industry buyer would bring. The case loads a realistic 3-6 table dataset for that problem, runs the full pipeline end-to-end, and asserts on process integrity (no errors, ≥40% of generated features survive dry-run, ≥3 source tables contribute features, AUC at least meaningfully above random).
| Case | Industry & problem | Tables | Status | AUC | Runtime | Runs |
|---|---|---|---|---|---|---|
ic_001 |
Industry: Healthcare — 90-day readmission prediction | — | ✓ | 0.745 | 1005s | 2 |
ic_002 |
Industry: SaaS — customer churn (90-day) | — | ✓ | 0.644 | 930s | 1 |
ic_003 |
Industry: E-commerce — repeat purchase (30-day) | — | ✓ | 0.769 | 313s | 2 |
ic_004 |
Industry: Banking — 90-day loan default | — | ✓ | 0.698 | 903s | 1 |
ic_005 |
Industry: Marketing — lead → SQL conversion | — | ✓ | 0.781 | 713s | 1 |
ic_006 |
Industry: Manufacturing — QC failure prediction | — | ✓ | 0.774 | 923s | 1 |
ic_007 |
Industry: Education — course-dropout prediction | — | ✓ | 0.773 | 938s | 1 |
ic_008 |
Industry: Insurance — claim fraud detection | — | ✓ | 0.732 | 298s | 2 |
Canonical suite
The small set of claims where we're not asserting a structural property — we're asserting an EXACT value. Each case has a hand-recorded answer key locked in validation/v2/cases/canonical_keys/; the assertion compares the pipeline's actual output to the locked value within tolerance. If anything in the pipeline changes its computation — model retrain, feature engineering, library upgrade — the canonical case fires. Re-recording the answer key is a deliberate act, like updating a snapshot test.
| Case | Locked claim | Status | Runtime | Runs |
|---|---|---|---|---|
cc_001 |
Canonical: v2 pipeline reproducibility on a fixed dataset | ✓ | 75s | 4 |
cc_002 |
Canonical: v2 pipeline AUC at strong signal (locked exact) | ✓ | 72s | 2 |
cc_003 |
Canonical: v2 pipeline AUC at weak signal (locked exact) | ✓ | 68s | 2 |
Deployment suite
Training is only half of the ML lifecycle. The other half is scheduled re-scoring: a trained model wakes up on a cadence, reads new rows, writes predictions, and must NOT silently corrupt history. The suite is layered — each lane catches regressions the lane below it can't see:
- Contract (
dc_*) — logical contract, synthetic data, in-process sklearn. Cheap and hermetic. - End-to-end (
dce_*) — real GCS round-trip + real BigQuery + realexecute_live_refresh. Catches GCS auth, pickle format drift, runtime-globals-dict regressions. - HTTP handler (
dch_*) — driveshandle_render_liveend-to-end (Firestore round-trip +re_render_htmlLLM). Includes happy path + the error matrix (404 missing project, 400 no spec, 400 empty sections). - Compose intent LLM (
dcc_*) — exercisesunderstand_deployment_goal(the LLM that decides per-section keep / transform_score / drop / augment at deploy time). Catches intent-classifier regressions before they ship to every new deployment. - Transform LLM (
dct_*) — exercisestransform_section_for_live(the LLM that rewrites a training section into a scoring section at deploy time). Catches prompt or AST-validator regressions. - Full lifecycle (
dcl_*) — the cherry on top: train → compose → transform → deploy → fire → read live_artifact, all real, no mocks. Slow (~1 min) and costly (~$0.05/run) but the only test that proves integration.
Cloud Run Job creation + Cloud Scheduler firing are NOT in this suite — those are deploy-time orchestration that GCP guarantees once deploy_to_cloud returns a valid job ID. The failure modes that actually affect daily refresh live inside the job body, which dce_* / dch_* cover.
Contract (dc_*)
Each row is a failure mode of the deployment contract — what any future scheduled-rescoring runner must satisfy. Runs against synthetic data with in-process sklearn; cheap, hermetic, fast.
| Case | Failure mode | Scored | Status | Runtime | Runs |
|---|---|---|---|---|---|
dc_001 |
Deployment: daily score refresh (happy path) | 100 | ✓ | 17s | 2 |
dc_002 |
Deployment: cold start (first-ever fire) | 100 | ✓ | 9s | 1 |
dc_003 |
Deployment: empty batch (schedule fires, nothing new) | 0 | ✓ | 8s | 1 |
dc_004 |
Deployment: schema drift — extra column upstream | 100 | ✓ | 16s | 1 |
dc_005 |
Deployment: schema drift — feature column missing upstream | 100 | ✓ | 13s | 1 |
dc_006 |
Deployment: late-arriving rows (idempotency) | 100 | ✓ | 14s | 1 |
dc_007 |
Deployment: model artifact missing | — | ✓ | 4s | 1 |
dc_008 |
Deployment: high-volume batch (10× normal) | 5000 | ✓ | 18s | 1 |
End-to-end (dce_*)
Same failure modes, but exercising the REAL production path: joblib-pickle a trained model to a real GCS bucket, upload source data to a real BigQuery table, invoke deployment_composer.skills.meta.execute_live_refresh.run_sections_capture_outputs. Slower (~10s/case) but this is the only lane that catches GCS auth issues, pickle format drift, or runtime-globals-dict regressions.
| Case | Failure mode | Scored | Status | Runtime | Runs |
|---|---|---|---|---|---|
dce_001 |
Deployment E2E: real GCS model + real BQ + real execute_live_refresh | 50 | ✓ | 10s | 4 |
dce_002 |
Deployment E2E: real GCS 404 — section error must surface | — | ✓ | 6s | 1 |
dce_003 |
Deployment E2E: real empty BQ source — no crash, empty result | 0 | ✓ | 6s | 1 |
dce_004 |
Deployment E2E: same recipe twice → identical section_outputs | 50 | ✓ | 11s | 1 |
HTTP handler (dch_*)
Drives deployment_composer_api.handle_render_live against a real Firestore project. Covers the full HTTP-handler contract: Firestore read of deployment_spec, invocation of execute_live_refresh (which calls the re_render_html Sonnet LLM), and the write-back of live_artifact.html to Firestore. ~40s/case — the LLM is the long pole.
| Case | Scenario | Status | Runtime | Runs |
|---|---|---|---|---|
dch_001 |
Deployment Handler: real handle_render_live → Firestore round-trip | ✓ | 43s | 4 |
dch_002 |
Deployment Handler: missing project → 404 with clean message | ✓ | 3s | 1 |
dch_003 |
Deployment Handler: project exists but no deployment_spec → 400 | ✓ | 2s | 1 |
dch_004 |
Deployment Handler: spec with empty sections_for_live → 400 | ✓ | 2s | 1 |
Compose intent LLM (dcc_*)
Pure-LLM round-trip against deployment_composer.skills.meta.understand_deployment_goal. Hands the LLM 3 sections with unambiguous intents (a KPI dashboard, a .fit() training block, a methodology blurb); asserts the LLM returns 'keep' on the dashboard and 'transform_score' on the training section. ~4s/case.
| Case | Scenario | Status | Runtime | Runs |
|---|---|---|---|---|
dcc_001 |
Deployment Compose: LLM assigns correct intents to a 3-section report | ✓ | 3s | 1 |
Transform LLM (dct_*)
Pure-LLM round-trip against deployment_composer.skills.meta.transform_section_for_live. Sends a training-flavored section (calls .fit()); asserts the LLM returns a rewrite that loads the saved model, doesn't fit anything, and references the literal model_uri. Catches prompt regressions before they corrupt every new deployment.
| Case | Scenario | Status | Runtime | Runs |
|---|---|---|---|---|
dct_001 |
Deployment Transform: LLM rewrites training section into live scoring | ✓ | 7s | 1 |
Orchestration (dco_*)
Real Cloud Scheduler create → verify config → teardown. Proves the contract for deploy_to_cloud: given a DeploymentSpec, the provisioner must create a scheduler entry with the right cron, timezone, HTTP target, body, and HMAC header — and teardown must cleanly remove it. ~3s/case. The contract is implementation-agnostic; any future rewrite has to pass these same assertions.
| Case | Scenario | Status | Runtime | Runs |
|---|---|---|---|---|
dco_001 |
Deployment Orchestration: create → verify config → teardown | ✓ | 3s | 10 |
dco_002 |
Deployment Orchestration: scheduler fires → backend refreshes → live_artifact updates | ✓ | 53s | 2 |
Full lifecycle (dcl_*)
End-to-end integration test: train a model, upload to GCS, upload source to BigQuery, run the composer (LLM intents), run the transform (LLM rewrites), persist DeploymentSpec to Firestore, fire handle_render_live (which calls execute_live_refresh and re_render_html), then read live_artifact back. The only test that proves all layers integrate. Slow (~1 min) and uses real Anthropic + real GCS + real BQ + real Firestore.
| Case | Scenario | Status | Runtime | Runs |
|---|---|---|---|---|
dcl_001 |
Deployment Lifecycle: train → compose → transform → deploy → fire → read | ✓ | 50s | 2 |
Regression suite
Every shipped fix has a case here that captures the failure mode it addressed — a tight regression guard. The matrix below shows which (data shape × analytics type) combinations are covered; · cells are honest gaps, not failures.
Coverage matrix
| data shape ↓ / analytics → | ml_binary | ml_regression | statistical | dashboard | cross_surface | analytical_report | deployment_orchestration_runtime |
|---|---|---|---|---|---|---|---|
entity_static |
✓ vc_001 |
· | · | · | ✓ vc_018 |
✓ vc_007 |
· |
panel_snapshot |
✓ vc_002 |
· | · | · | · | ✓ vc_008 |
· |
event_level |
· | · | · | · | · | ✓ vc_012 |
· |
multi_table |
✓ vc_004 |
· | · | · | · | ✓ vc_009 |
· |
high_card_categorical |
✓ vc_013 |
· | · | · | · | · | · |
degenerate_label |
✓ vc_005 |
· | · | · | · | · | · |
entity_static_with_leak |
✓ vc_003 |
· | · | · | · | · | · |
entity_with_segments |
· | · | ✓ vc_010 |
· | · | ✓ vc_006 |
· |
entity_static_regression |
· | ✓ vc_011 |
· | · | · | · | · |
entity_with_duplicates |
✓ vc_014 |
· | · | · | · | · | · |
entity_with_finer_source |
○ vc_021 |
· | · | · | · | · | · |
entity_mixed_type_numeric |
✓ vc_015 |
· | · | · | · | · | · |
entity_high_null_column |
✓ vc_016 |
· | · | · | · | · | · |
entity_date_as_varchar |
✓ vc_017 |
· | · | · | · | · | · |
panel_per_table_time_col |
✓ vc_019 |
· | · | · | · | · | · |
event_stream_entity_table |
✗ vc_020 |
· | · | · | · | · | · |
Recent failures
Cases that did not pass on their latest run. Every failure is disclosed here, not silently retried.
vc_020 — Event-stream entity table (Forj retention shape) (regression suite)
- AuthenticationError: Error code: 401 - {'type': 'error', 'error': {'type': 'authentication_error', 'message': 'API key is invalid.'}, 'request_id': None}
- Case detail →
All cases
| Case | Suite | Name | Status | Data shape | Analytics | Runs |
|---|---|---|---|---|---|---|
cc_001 |
canonical | Canonical: v2 pipeline reproducibility on a fixed dataset | ✓ | entity_static |
ml_binary |
4 |
cc_002 |
canonical | Canonical: v2 pipeline AUC at strong signal (locked exact) | ✓ | entity_static |
ml_binary |
2 |
cc_003 |
canonical | Canonical: v2 pipeline AUC at weak signal (locked exact) | ✓ | entity_static |
ml_binary |
2 |
dc_001 |
deployment | Deployment: daily score refresh (happy path) | ✓ | deployment_score_refresh |
deployment |
2 |
dc_002 |
deployment | Deployment: cold start (first-ever fire) | ✓ | deployment_cold_start |
deployment |
1 |
dc_003 |
deployment | Deployment: empty batch (schedule fires, nothing new) | ✓ | deployment_empty_batch |
deployment |
1 |
dc_004 |
deployment | Deployment: schema drift — extra column upstream | ✓ | deployment_schema_drift_extra |
deployment |
1 |
dc_005 |
deployment | Deployment: schema drift — feature column missing upstream | ✓ | deployment_schema_drift_missing |
deployment |
1 |
dc_006 |
deployment | Deployment: late-arriving rows (idempotency) | ✓ | deployment_late_rows |
deployment |
1 |
dc_007 |
deployment | Deployment: model artifact missing | ✓ | deployment_model_missing |
deployment |
1 |
dc_008 |
deployment | Deployment: high-volume batch (10× normal) | ✓ | deployment_high_volume |
deployment |
1 |
dcc_001 |
deployment | Deployment Compose: LLM assigns correct intents to a 3-section report | ✓ | deployment_compose_happy |
deployment_compose |
1 |
dce_001 |
deployment | Deployment E2E: real GCS model + real BQ + real execute_live_refresh | ✓ | deployment_e2e_happy |
deployment_e2e |
4 |
dce_002 |
deployment | Deployment E2E: real GCS 404 — section error must surface | ✓ | deployment_e2e_model_missing |
deployment_e2e |
1 |
dce_003 |
deployment | Deployment E2E: real empty BQ source — no crash, empty result | ✓ | deployment_e2e_empty_source |
deployment_e2e |
1 |
dce_004 |
deployment | Deployment E2E: same recipe twice → identical section_outputs | ✓ | deployment_e2e_determinism |
deployment_e2e |
1 |
dch_001 |
deployment | Deployment Handler: real handle_render_live → Firestore round-trip | ✓ | deployment_handler_happy |
deployment_handler |
4 |
dch_002 |
deployment | Deployment Handler: missing project → 404 with clean message | ✓ | deployment_handler_missing_project |
deployment_handler |
1 |
dch_003 |
deployment | Deployment Handler: project exists but no deployment_spec → 400 | ✓ | deployment_handler_no_spec |
deployment_handler |
1 |
dch_004 |
deployment | Deployment Handler: spec with empty sections_for_live → 400 | ✓ | deployment_handler_empty_sections |
deployment_handler |
1 |
dcl_001 |
deployment | Deployment Lifecycle: train → compose → transform → deploy → fire → read | ✓ | deployment_lifecycle_happy |
deployment_lifecycle |
2 |
dco_001 |
deployment | Deployment Orchestration: create → verify config → teardown | ✓ | deployment_orchestration_happy |
deployment_orchestration |
10 |
dco_002 |
deployment | Deployment Orchestration: scheduler fires → backend refreshes → live_artifact updates | ✓ | deployment_orchestration_runtime |
deployment_orchestration_runtime |
2 |
dct_001 |
deployment | Deployment Transform: LLM rewrites training section into live scoring | ✓ | deployment_transform_happy |
deployment_transform |
1 |
ic_001 |
industry | Industry: Healthcare — 90-day readmission prediction | ✓ | industry_healthcare_readmission |
ml_binary |
2 |
ic_002 |
industry | Industry: SaaS — customer churn (90-day) | ✓ | industry_saas_churn |
ml_binary |
1 |
ic_003 |
industry | Industry: E-commerce — repeat purchase (30-day) | ✓ | industry_ecommerce_repeat_purchase |
ml_binary |
2 |
ic_004 |
industry | Industry: Banking — 90-day loan default | ✓ | industry_banking_loan_default |
ml_binary |
1 |
ic_005 |
industry | Industry: Marketing — lead → SQL conversion | ✓ | industry_marketing_lead_conversion |
ml_binary |
1 |
ic_006 |
industry | Industry: Manufacturing — QC failure prediction | ✓ | industry_manufacturing_defect |
ml_binary |
1 |
ic_007 |
industry | Industry: Education — course-dropout prediction | ✓ | industry_education_dropout |
ml_binary |
1 |
ic_008 |
industry | Industry: Insurance — claim fraud detection | ✓ | industry_insurance_fraud |
ml_binary |
2 |
vc_001 |
regression | Entity-static control | ✓ | entity_static |
ml_binary |
19 |
vc_002 |
regression | Snapshot panel | ✓ | panel_snapshot |
ml_binary |
13 |
vc_003 |
regression | Leak guard | ✓ | entity_static_with_leak |
ml_binary |
7 |
vc_004 |
regression | Multi-table aggregation | ✓ | multi_table |
ml_binary |
17 |
vc_005 |
regression | Degenerate label | ✓ | degenerate_label |
ml_binary |
7 |
vc_006 |
regression | Descriptive analytics — segment questions | ✓ | entity_with_segments |
analytical_report |
7 |
vc_007 |
regression | Descriptive analytics — single-table entity data | ✓ | entity_static |
analytical_report |
6 |
vc_008 |
regression | Descriptive analytics — monthly client panel | ✓ | panel_snapshot |
analytical_report |
3 |
vc_009 |
regression | Descriptive analytics — multi-table (clients × transactions) | ✓ | multi_table |
analytical_report |
3 |
vc_010 |
regression | Statistical analysis — segment-mean significance | ✓ | entity_with_segments |
statistical |
3 |
vc_011 |
regression | Entity-static regression | ✓ | entity_static_regression |
ml_regression |
2 |
vc_012 |
regression | Descriptive analytics — user event log | ✓ | event_level |
analytical_report |
1 |
vc_013 |
regression | High-cardinality categorical encoding | ✓ | high_card_categorical |
ml_binary |
2 |
vc_014 |
regression | Entity table with duplicate keys (fail-fast) | ✓ | entity_with_duplicates |
ml_binary |
3 |
vc_015 |
regression | Mixed-type numeric column (currency as STRING) | ✓ | entity_mixed_type_numeric |
ml_binary |
3 |
vc_016 |
regression | High-NULL demographic column | ✓ | entity_high_null_column |
ml_binary |
2 |
vc_017 |
regression | Date column stored as VARCHAR (panel) | ✓ | entity_date_as_varchar |
ml_binary |
3 |
vc_018 |
regression | Cross-surface — chat → ML → chat | ✓ | entity_static |
cross_surface |
3 |
vc_019 |
regression | Panel + multi-table with per-source time columns | ✓ | panel_per_table_time_col |
ml_binary |
7 |
vc_020 |
regression | Event-stream entity table (Forj retention shape) | ✗ | event_stream_entity_table |
ml_binary |
2 |
vc_021 |
regression | Source declared finer than the modeling grain (aggregate, don't refuse) | — | entity_with_finer_source |
ml_binary |
0 |
See methodology.md for how cases are constructed, what assertion kinds mean, and how failures are disclosed.