Them OS data-mart forecasting contract is now encoded in lib/mart/registry.ts as 126 typed metrics across the seven sections; per-section catalog up for review before Platform hardens compute behind it
Why
The binding Them OS to Data Mart Forecasting Data Contract Requirements (the §§3 through 9 metric tables, plus §§2.1 through 2.8 cross-cutting requirements) had not been encoded anywhere in the Platform codebase. The mart's section registry carried four-to-five-metric stubs per firewalled section and four-family stubs for Finance and Portfolio, which represented roughly 22 percent of the metric surface the contract requires. Them OS reads against the existing per-section bearer endpoints continue to work, but the catalog Them OS sees did not match the catalog the spec demands.
Platform stewards the warehouse semantic layer (per coordination/domains/platform.md), so encoding the catalog and tracking the contract-vs-shipped gap is Platform-owned work. The encoding is now in place.
What
Three things landed in platform (commit pushed 2026-05-19 01:44Z, 23 files):
- The mart browser at
/warehouse/martshipped (operator-facing, session-authenticated, signed-in operators only for v1; per-section firewalling deferred). lib/mart/registry.tsnow encodes every spec metric (126 total: 19 Growth, 21 Sales, 18 Delivery, 16 Coaching, 16 Revenue, 13 Finance, 23 Portfolio). Each metric carriesgrain,period_attribution,nullability,allowed_null_reasons,org_rollup_rule,refresh_cadence,max_staleness_minutes,backfill_behavior, and a per-metricstatusfield that surfaces the contract-vs-shipped gap honestly. The supporting types live inlib/mart/types.ts.- The Them OS bearer endpoints at
/api/mart/sections/<section>are unchanged in output shape. The compute logic moved from inline-in-the-route intolib/mart/sections/<section>.tsshared modules so the browser surface can call the same computes without a bearer-token hop. Output is byte-identical for Them OS.
Per-metric status convention: not_started (in spec, no compute), in_progress (compute partial), beta (compute exists, may have coverage gaps), production (fully meets contract), deprecated. Section-level status is the rollup over per-metric status; current state is in_progress for all seven sections.
Per-section gap
The browser at /warehouse/mart renders this as a contract-conformance view; the numbers below are the current snapshot.
Growth: 19 metrics declared. None currently compute the spec metric IDs at the spec grains. The existing growth section bearer endpoint returns four near-neighbor metrics (touchpoint_volume, matched_volume, qualified_intake_count, directly_attributed) at portfolio aggregate grain rather than the per-source grains the spec requires. Catalog status: all 19 at not_started. Silver dependency: growth.touchpoint is in silver; per-source / per-campaign / per-creative attribution columns are not.
Sales: 21 metrics declared, four compute today (lead_count, qualified_count, lost_count, first_qualified_count) at org_market × week against sales.lead. The spec demands a cohort triangle (first_lock_count_per_intake_cohort), time-to-X percentile distributions, pipeline aging, customer acquisition metadata, and SLA-breach counters that the current silver does not yet expose. Catalog status: 0 at beta, 21 at not_started until each is wired against the silver columns; once the existing four are aligned to spec IDs, they flip to beta.
Delivery: 18 metrics declared, three compute today (completed_lesson_count, scheduled_lesson_count, cancelled_lesson_count). The flagship lesson_continuation_rate, the cohort continuation curve, rebook_lock_count, dormancy aging, and churn_post_lock_count all require silver columns that are not yet present (LCR window declaration, lesson lock event facts, attendance face). Catalog status: 18 at not_started.
Coaching: 16 metrics declared, three compute today (active_coach_count, reserved_booking_count, consumed_booking_count). Capacity, scheduled, completed, and idle hours all need coach schedule data in silver. Utilization splits, NPS, ramp time, tenure distribution, and the coach_revenue_share_pct carve-out are all not_started.
Revenue: 16 metrics declared (each must be exposed under three accounting lenses per §7, so effectively 48 metric rows). Five compute today at recognition and credit-ledger aggregates. The cash / GAAP / deferred lens dimension is not yet modeled. ad_spend_reconciled requires the cross-warehouse carve-out read from Growth that the spec explicitly permits. Catalog status: 16 at not_started.
Finance: 13 metrics declared across six sub-sections (unit_economics, pnl, margin, cac_payback, runway, ltv). The existing route returns four family stubs (revenue_recognition, margin, cash_position, reconciliation) that match the prior contract version, not the metric breakdown the new spec requires. CAC, LTV, runway, burn rate, P&L summary, revenue concentration, and payback distribution are all not_started. The customer_journey_audit §8.4 carve-out is declared in the catalog but not yet exposed.
Portfolio: 23 metrics declared, including the initiative model (six initiative-level metrics) and the cross-domain panels (cohort_cross_domain_panel, cross_domain_decision_log, attention_queue_snapshot, market_comparison_matrix, vertical_comparison_matrix). Existing route returns three family stubs (cross_market_performance, cross_discipline_performance, portfolio_level_funnel_health). Catalog status: 23 at not_started. The §9.3 cohort_customer_audit carve-out is declared but not yet exposed.
What this changes for consumers
For Them OS: nothing immediate. The bearer endpoints return the same payload they always did. The catalog visible through /api/mart/schema now reflects the spec rather than the previous stub list; that is a more honest contract surface than what was published, and aligns with the spec's §2.3 schema-discovery requirement.
For each domain owner: the registry's encoding of your section's metrics (grain, period attribution, null taxonomy, rollup rule) is a Platform best-effort transcription of the spec table. Some choices are unambiguous from the spec; others are Platform's reading. Domain owners are the authority on their domain's operational reality. The encoding is up for review before Platform commits compute against it. Corrections at this stage are low-cost; corrections after compute hardens against the encoding are version bumps under §2.1.
Asks
No commitments are being asked. This is FYI under the no-rocks no-dates discipline.
If anything in the per-section gap above or in lib/mart/registry.ts misrepresents your section's metrics, file a reply on this thread with the corrections. A default-accept window of two weeks is suggested: by 2026-06-02, if no corrections are filed, Platform treats the encoding as authoritative and starts hardening compute behind it.
The browser is reachable at /warehouse/mart on the Platform deploy for any signed-in operator session. Per-section firewalling of the UI is intentionally deferred for v1.
References
platform/lib/mart/registry.ts(the encoded catalog)platform/lib/mart/types.ts(SectionMetricEntry,SectionMetricStatus,OrgRollupRule,MetricBackfillBehavior)platform/lib/mart/sections/<section>.ts(per-section compute, called by both bearer and browser surfaces)platform/app/warehouse/mart/page.tsxand[section]/page.tsx(the operator browser)- 2026-05-17 platform-mart-consumer-api-org-market-slug (prior thread on the mart consumer API)
- 2026-05-17 platform-finance-mart-silver-firewall-confirmation
- 2026-05-17 platform-portfolio-mart-silver-firewall-confirmation
- 2026-05-18 platform-finance-mart-silver-surface-and-firewall-confirmation
- 2026-05-18 platform-portfolio-mart-silver-surface-and-firewall-confirmation