Metric Market — plain-language explainer
Metric Market is the workbench where a curator turns a pile of computed numbers into an ordered, self-explaining board of metric cards — with the most consequential cards already sorted to the top.
A People Analytics Toolbox consumer surface (PAT-21), not a spoke. It owns no schema and no algorithm; it composes other spokes' public APIs and contract types into a UI a person actually meets. Built to the portfolio Explainer Standard v1.0. Every claim below is grounded in the surface's own code (src/surfaces/metric-market/, route src/app/(surfaces)/metric-market/) and the contracts it imports; anything not yet built is marked (TBD).
Lead
Give it a metric × segment × period grid and a cohort, and Metric Market hands back a board of cards — each a single defensible number with its band, its delta, and its provenance — arranged so the high-impact, high-confidence findings read first.
It is a workbench, not a dashboard: the point is composing and curating the board, not just looking at one.
Manifesto — why it exists
The pain it removes is the moment after the numbers are computed and before anyone can act on them. A statistics engine can produce hundreds of metric-by-segment-by-period cells. Most tools then dump all of them onto a screen in arrival order, or in whatever order a hand-built layout froze last quarter — leaving a human to scan for the few that matter and to remember, cell by cell, which were significant and which were noise.
Metric Market's worldview is that placement is a finding. Where a card sits on the board is itself information, and it should be derived from the statistics, not from who dragged what where. A metric with a tight confidence interval and a large, well-sampled change has earned the top-left; a metric whose band is wide enough to swallow its own movement has not, and should fall down the page on its own.
The differentiation beat, stated as a shift:
- FROM an undifferentiated wall of metric tiles in arrival order, where the reader does the triage and the uncertainty is buried in a tooltip.
- TO a board ordered by an enrichment-derived placement score, where each card surfaces its own confidence interval, delta, sample size, and significance band, and where the cards that can't defend themselves sink.
How it differs from the obvious substitutes:
- vs. building the board by hand — a hand-laid grid encodes last quarter's intuition and goes stale silently; Metric Market re-derives the order from this run's enrichment every time it loads (
force-dynamic), so the ordering tracks the data, not the layout file. - vs. generic BI — a BI tool will happily render a wide-band estimate the same size and weight as a survey-grade observation. Metric Market reads the enrichment off the MetricEnvelope and lets relative CI width demote a card; the honesty is structural, not a label the author chose to add.
Visual — Tier B (FROM→TO typographic block). The shift above is the visual. The placement rule, verbatim from card-metadata.ts, is: a card's priority is max(impact, significance) × 1.25 + relevance × 0.35; higher sorts earlier. Significance itself is derived from relative CI width — 100 / (1 + ciWidth × 50) — so a wider band mechanically lowers the card's standing.
Walkthrough — how it actually works
The surface is a server component (CardWorkbench) that assembles a board on each request, then hands it to a client grid the curator can reorder and save. The journey through it:
-
Discovery. On load it calls
GET /api/registryandGET /api/healthand shows a discovery strip — registryok/unavailable, aggregate health overall. This is the surface telling you, up front, whether the spokes it depends on are reachable before it shows you any numbers. -
Build the grid (calculus). It POSTs a
FactoryBuildRequesttoPOST /api/spokes/calculus/factory/build— the calculus factory — with a metric × segment × period specification and avaluesProviderof raw rows. The factory returns enrichedMetricEnvelopes (value + sample size + provenance + optional enrichment: CI, z-score, percentile, change rate). Each envelope becomes onemetric-card. The default build (default-build.ts) requests two metrics (engagement_score,completion_rate) across three seeded PAT-5 segments (engineering, sales, product) for2026-Q1, withrankingStrategy: "impact". -
Resolve a cohort (segmentation-studio). It POSTs to
POST /api/spokes/segmentation-studio/cohorts/resolvewith include-criteria (department ∈ engineering AND region ∈ west) against seeded PAT-5 nodes. The resolved cohort — total members, total nodes — becomes ametric-segment-list-card. This is a live resolve, not a fixture: it is the surface demonstrating that "the segment" is itself a computed object. -
Recommend a chart (PAT-43 viz catalog). For the engagement series it calls
inferVizForEnvelopefrom the visualization catalog with the envelope's shape (distribution kind, cohort dimensionsegment, three segments). The catalog returns a recommended template id and a rationale string — the chart choice is auditable, not hidden. That becomes aviz-card. -
Derive placement metadata. Every card gets a
CardMetadata(relevance,significance,impact,recency,tags) derived from its source —metadataFromEnvelopereads the calculus enrichment;metadataFromCohortscales by member/node counts;metadataForVizis a flat default. The board is then sorted byplacementPriorityso impact and significance lead. -
Curate. The assembled board is handed to the client
MetricMarketGrid. The curator can reorder cards and save a named layout (saveLayout→localStorage, e.g. "Q1 review") and re-apply it later. The auto-derived order is the starting point; the human override is preserved per browser.
The differentiation beat for the practitioner: the real question on meeting a board of numbers is "which of these do I act on, and can I defend the order to my VP?" Metric Market answers both — the order is computed from the statistics, and each card carries the evidence (band, n, delta, significance) inline.
Visual — Tier B (in-repo step flow). The assembly pipeline, from assemble-cards.ts:
FactoryBuildRequest → POST calculus/factory/build → MetricEnvelope[] → metric-cards · in parallel cohorts/resolve → metric-segment-list-card · inferVizForEnvelope → viz-card → sortWorkbenchCards (placementPriority desc) → MetricMarketGrid (reorder + save layout).
What it enables
Concrete uses a curator or analyst would recognize:
- Stand up a quarterly review board — point the factory build at this quarter's metrics and segments and get a pre-triaged board where the movements that survived their own confidence interval are already on top.
- Curate a stakeholder-specific layout — reorder the auto-sorted board for a specific audience and save it as a named layout, without losing the data-derived default underneath.
- Spot the indefensible movement — a metric that looks like it moved but whose card has sunk (wide relative CI → low significance) is the surface flagging "don't lead with this one."
- See the cohort as a first-class object — the resolved-cohort card shows that "engineering in the west" is a computed membership with a count, not a label typed into a filter.
- Read the chart rationale — each viz-card can carry why that template was chosen (the catalog's rationale string), so the chart selection is reviewable.
- Compose without cross-wiring — pull calculus envelopes and segmentation cohorts into one board purely over HTTP + contracts, with no spoke importing another spoke's internals.
Visual — (TBD — a screen capture of the live /metric-market board with the discovery strip + sorted cards).
How it fits in the toolbox
Metric Market is a surface: it owns page routes under /metric-market and composes spokes through their public HTTP APIs and contract types only — never another spoke's core/ or db/. The boundary is the architecture rule, and this surface honors it.
- Composes — calculus (
@/spokes/calculus/contracts/types): theFactoryBuildRequest/MetricEnvelope/ enrichment contract viaPOST /api/spokes/calculus/factory/build. Calculus is the numerical brain; Metric Market is one of its readers. See the calculus explainer for the envelope and factory internals. - Composes — segmentation-studio (
@/spokes/segmentation-studio/contracts/types): theResolveCohortResponseviaPOST /api/spokes/segmentation-studio/cohorts/resolve. Cohorts are resolved live against seeded PAT-5 nodes. - Composes — the PAT-43 visualization catalog (
@/lib/visualizations/registry, a cross-cuttingsrc/lib/primitive, not a spoke):inferVizForEnveloperecommends a template id + rationale from envelope shape. - Reuses — the metric-card UI primitive (
@/components/primitives/metric-card):metric-card-adapter.tsmaps aMetricEnvelope+CardMetadatainto the sharedMetricDatashape (value, unit, delta, CI bounds, sample size, significance band). - Discovery —
GET /api/registry,GET /api/health. - Auth — the factory build and cohort resolve are POSTs, so they carry
TOOLBOX_SERVICE_KEYon the server side in production (requireServiceKeygate); discovery GETs are public. - Sibling surface — the Decision Wizard (
/decision-wizard, Kepner–Tregoe + value-of-information via forecasting), linked from the page header. Both are PAT-2x consumer surfaces over the same spoke fabric.
A note on the Insight Card relationship: Metric Market defines its own card union (WorkbenchCard = metric-card | metric-segment-list-card | viz-card) for the workbench's curator-facing placement model. It does not import the cross-spoke Insight Card contract (src/lib/insight-player/contract.ts) today; the two are kindred ideas — a card with metadata-driven sequencing — but the wiring between them is (TBD / not yet built).
Visual — Tier B (typographic data-flow). calculus factory/build + segmentation cohorts/resolve + PAT-43 inferViz → assembleWorkbenchCards → WorkbenchCard[] (metric · cohort · viz) → placementPriority sort → /metric-market board. Discovery (/api/registry, /api/health) gates the strip above the board.
One load-bearing worked example
This is the surface's own default build (default-build.ts) run end to end. All input values below are verbatim from the in-repo seed; all derived values follow the surface's own formulas in card-metadata.ts and the catalog branch in inferVizForEnvelope.
Input — the engagement_score row for the product segment (seed):
- value
88, previousValue79, sampleSize55, period2026-Q1, segmentpat5-node-product.
Step 1 — calculus enriches it. The factory derives a change rate from 88 vs 79 (changeRate ≈ +0.114, i.e. +11.4%) and may attach a CI/z-score/percentile (exact enrichment is the factory's, computed at request time).
Step 2 — Metric Market derives placement metadata (metadataFromEnvelope): with no CI present, significance falls back to |z| × 12; impact is min(100, |changeRate| × (n+1) × 2.5) = min(100, 0.114 × 56 × 2.5) ≈ 16. Engineering (82 from 78, n 120) and product both carry positive change, but product's large relative jump and engineering's large sample size each lift impact differently — so the board orders these three engagement cards by placementPriority, not alphabetically.
Step 3 — the viz-card. With three segments, envelopeKind: "distribution", cohortDimension: "segment", inferVizForEnvelope returns — verbatim from the catalog branch (registry.ts lines 93–98):
- recommended template:
viz.compa-ratio-distribution - alternatives:
["viz.distribution-histogram"] - rationale: "Multi-cohort distribution (segment) — stacked per-cohort histograms keep distribution shapes visually honest."
Step 4 — the cohort card. cohorts/resolve returns the live membership for department ∈ engineering AND region ∈ west against seeded PAT-5 nodes; its card's metadata scales with totalMembers and totalNodes (exact counts depend on the live seed at request time, so they are not asserted here).
What the curator does with it: the engagement-by-segment cards and the recommended compa-ratio-distribution viz sit at the top of the board (high impact/significance); the curator reorders for a stakeholder, saves the layout as "Q1 review," and the data-derived order remains the default on the next load.
No number above is invented: the inputs are the seed rows; the derived figures are this surface's own formulas applied to those rows; the viz rationale is the catalog's literal output for this shape.
Visual — Tier B (the worked board, top-down): [viz.compa-ratio-distribution: engagement by segment] · [metric-card engagement product +11.4%] · [metric-card engagement engineering] · [metric-card completion_rate …] · [cohort: engineering ∩ west], ordered by placementPriority.
Commercialization / packaging
Metric Market is a toolbox-internal consumer surface, not a separately sold product. It is the reference workbench that demonstrates the metric-card composition pattern over the calculus + segmentation spokes — the kind of UI a buyer-facing analytics offering composes, rather than a SKU on its own.
- Data-license posture: the default board runs on seeded PAT-5 demo data under the
__internal_demo__tenant; it is explicitly not tenant-bound yet (gated on PAT-39-FU-D, perdefault-build.ts). No customer or vendor-licensed data is involved in the shipped demo. - Product-tier placement, pricing, and any packaged offering are (TBD) — not earned yet, so not stated.
Visual — (TBD — product-tier placement diagram, deferred until the surface is tenant-bound).
Current status
Grounded in the real code state (src/surfaces/metric-market/, route src/app/(surfaces)/metric-market/page.tsx):
- Shipped: the live workbench at
/metric-market— server-side discovery strip (registry + aggregate health); a board assembled from a live calculus factory build (three card kinds: metric, cohort, viz); enrichment-derived placement sorting; a recommended chart with rationale from the PAT-43 catalog; client-side reorder and named-layout save tolocalStorage. It composes calculus (contract1.13.0) and segmentation-studio via HTTP + contract types only. - In flight / planned (from the surface README + inline TODOs):
- Full lift of the legacy
metric-marketdonor — range builder, insight player, etc. —(TBD)(assignmentdocs/ASSIGNMENTS/CURSOR/pat-21-metric-market-surface.md). - Comp range simulation → a future anycomp-related surface (PAT-21-FU) —
(TBD). - Per-user auth and server-persisted saved layouts (today's layouts are per-browser
localStorage) —(TBD). - Tenant binding beyond
__internal_demo__(PAT-39-FU-D) —(TBD). - Wiring to the cross-spoke Insight Card contract (
src/lib/insight-player/) —(TBD).
- Full lift of the legacy
Visual — Tier B (status as live capabilities). Live: discovery strip · factory-built metric cards · live cohort resolve · catalog-recommended viz · reorder + save layout. Not yet: range builder · comp simulation · server-persisted layouts · tenant binding · Insight Card wiring.
The vision
A self-curating board where every number arrives already triaged — high-confidence, high-impact findings on top, indefensible ones sunk — and the curator's job shifts from hunting to deciding.
Where it goes: from a demo over seeded PAT-5 data toward a tenant-bound workbench whose boards compose any spoke's envelopes, whose layouts persist per user, and whose card-and-sequencing model converges with the cross-spoke Insight Card contract — so a metric card curated here can flow into the same player that serves exec outputs elsewhere in the portfolio. The throughline is constant: placement is a finding, and the board should derive it from the statistics every time.
Visual — (TBD — a before/after of an arrival-order wall vs. the placement-sorted board for the same metrics).