# 10 — Palantir J8: Exhibit Factory **Rank 22 of 28** · Tier B · `Palantir/J8` **Stack:** Python (Foundry Tier 2 transforms), TypeScript + React + Vite (Foundry custom widget), pytest, vitest **Scope:** 172,545 lines across the Palantir tree; 20 pytest + 5 vitest green, `tsc` clean > **Why this ranks here.** This is the **financial-data-pipeline** entry, and > for a bank it is the most directly relevant project in the portfolio: typed > ontology, deterministic normalization, reference qualification, and an ingest > that *blocks on warnings* rather than passing bad data downstream. --- ## What it is A pipeline that turns heterogeneous financial workbooks into ontology-conformant exhibits, plus the Foundry custom widget that renders and edits them. ### Backend — `Tier2/python/ExhibitFactory` | Module | Role | |---|---| | `catalog.py`, `datasets.py` | Dataset registry and resolution | | `keyio.py` | Exhibit key parsing / emission | | `tokens.py` | Token grammar for cell and reference addressing | | `refs.py` | **Reference qualification — label-first resolution** | | `normalize/` | Per-shape normalizers: `flat_fy_rows`, `flat_pycyby`, `cash_monthly`, `multi_subsheet`, `f1_transition`, `user_input`, driven by a `registry` | | `compute/resolver.py` | Derived-value resolution | | `transforms/ingest.py` | The ingest transform | | `fixture.py`, `tools/make_widget_fixture.py` | Fixture generation for the widget | The normalizer registry is the good design here: each input shape gets a named, tested normalizer, and dispatch is data-driven rather than a branching `if`-ladder. Adding a shape is adding a module and a registry entry. ### Frontend — `CustomWidget` React + TypeScript + Vite Foundry widget with a config-driven main entry, an ontology client layer, and screen-level views. `tsc` clean, 5 vitest green. ### Rebuilt on ontology v7 The whole system was re-derived against ontology v7 rather than patched forward, with **reference qualification changed to label-first**. F-5 proven; the transposed-3 case is **WARN-blocked** — it does not silently produce a wrong exhibit, it stops. > Refusing to emit output you cannot vouch for is the single most > bank-relevant instinct in this repository. ## Verification | Suite | Result | |---|---| | pytest | 20 green | | tsc | clean | | vitest | 5 green | Tests target behavior that matters: `test_recipe_families`, `test_tokens`, `test_factory_f5`, `test_ingest_merge`, `test_warn_blocked`. ## Interview surface this opens - Ontology / schema-driven pipelines and versioned migration (v6 → v7) - Data-driven dispatch vs conditional branching for heterogeneous inputs - Fail-closed ingest: when a warning should block a pipeline - Deterministic transforms and fixture-based testing across a language boundary