peopleanalyst

← Portfolio

People Analytics Toolboxpeopleanalyticstoolbox.com

↻ brief 5d ago

Independently-versioned analytical microservices for people analytics — psychometric diagnostics, preference modeling, privacy primitives, segmentation, statistical enrichment, compensation logic, decision forecasting, metadata-grounded codegen — deployed as a single Next.js application and exposed over two transports: HTTP for engineers, MCP for AI agents. One Vercel project, one Supabase project. The behavioral and statistical substrate consumer apps compose against.

Microstory
Customer
Enterprise HR teams that want analytics-grade infrastructure with behavioral and statistical discipline underneath, plus consumer applications that want a typed, AI-callable service substrate to compose against instead of rebuilding the same five primitives over and over.
Problem · external
HR analytics products treat behavioral data as if it were transactional — engagement becomes a survey score, performance a rating average, retention a churn rate, compensation a band — and every product re-implements anonymization, metrics, segmentation, surveys, and decision support slightly wrong.
Problem · internal
The richer questions — what actually drives engagement here, what signal in the distribution matters, what posture handles small-N honestly, what value would more information have before another study runs — get lost in the dashboards.
Problem · philosophical
Wrong analytical posture and fragmented infrastructure are the field's default state, and that default produces decisions about people that the data was never built to support.
Guide
The toolbox is the substrate, not the product — typed Zod contracts, per-spoke schemas, per-spoke audit, every algorithm callable from engineers over HTTP and from AI agents over MCP without bespoke integration.
Plan
Adopt spoke-by-spoke; vendor only the typed contracts; compose via HTTP for engineers or MCP for AI agents; no all-or-nothing migration.
Success
Behavioral science and statistical rigor sit underneath every product instead of bolted on — constructs defined defensibly, anonymity enforced in the contract, decisions getting value-of-information treatment, small-N segmentations handled honestly.
Failure avoided
Five products each re-implementing the same five primitives slightly wrong, with no shared audit trail, no shared contracts, and no shared posture on what "honest" looks like.
The problem

HR analytics products treat behavioral data as if it were transactional. Engagement gets reduced to a survey score; performance to a rating average; retention to a churn rate; compensation to a band. The richer questions — what actually drives engagement in this organization, what signal in performance distributions matters for decisions, what statistical posture handles small-N segmentations honestly, what value would more information have before another study runs — get lost. Cross-cutting concerns (anonymization, metric calculation, segmentation, survey delivery, decision support) also get re-implemented per product, brittle and fragmented. The combination — wrong analytical posture and fragmented infrastructure — is the field's default state.

What I built

Live spokes — reincarnation (adaptive psychometric diagnostic engine; IRT-weighted item selection; pool-based item lifecycle), preference-modeler (Likert/multi-choice/free-text plus MaxDiff, conjoint, penny allocation, paired comparison; BIBD-balanced task generation; MNL utility estimation via Newton-Raphson), data-anonymizer (PII detection, deterministic HMAC tokenization, k-anonymity min-N gate, substitution-strategy registry), segmentation-studio (HRIS canonical-field normalization with 35-field priority catalog; multi-membership cohort resolution; OneModel adapter; recipes; pack publishing), calculus (statistical enrichment, anomaly detection, time-series imputation, metric × segment × period combinatorial factory; auto-selects Wilson / t-interval / normal CI), anycomp (comp models, market band math, stateless evaluation, auditable cycle runs), forecasting (Monte Carlo simulation, EVPI, discrete EVSI on aligned-chance decision trees), and Conductor (metadata-grounded SQL/Python codegen — the model sees schema, field semantics, and canonical metric definitions, so the queries it produces are construct-honest by construction) — plus a reserved namespace job-family-agent whose canonical home is meta-factory-prod. Each spoke owns its own schema, contract, and audit trail. Per-route structured logs plus per-tool audit rows in mcp.mcp_audit. Consumer apps vendor the typed contracts; the algorithms live here.

What's novel
  • 01Substrate, not product. Consumer apps (Performix, vela, future analytical products) vendor only the typed Zod contracts; the algorithms stay in the toolbox. Adoption is spoke-by-spoke; no all-or-nothing migration.
  • 02AI-native by construction. Every spoke is callable from AI agents over MCP (Model Context Protocol) without bespoke integration. Per-consumer auth, scope-restricted keys, fire-and-forget audit log. Performix migrated to MCP transport 2026-05-11 as the first external consumer; devplane operates the wildcard key.
  • 03Behavioral science in the algorithms, not bolted on. Reincarnation runs IRT a-parameter-weighted adaptive item selection with Cronbach α tracking. Preference-modeler runs MNL utility estimation on real MaxDiff/conjoint designs. Calculus auto-selects the right confidence-interval method by data shape. These are textbook psychometrics and choice theory implemented as service APIs.
  • 04Conductor: metadata-grounded codegen — the model sees schema, field semantics, and canonical metric definitions, so the SQL/Python it produces is construct-honest by construction, not example-grounded. Bridges the gap between an AI writing queries and an AI writing queries that respect what the constructs are supposed to mean.
  • 05Privacy is a service, not a setting. Data-anonymizer is cross-cutting — every spoke that surfaces team-level rollups calls min-N-check before responding. Anonymity-gated aggregations return blocked status below the floor; tokenization is deterministic and cache-backed; substitution strategies (mask / pseudonymize / synthetic-realistic) live in a registry.
  • 06Systems × survey × behavioral-science join is first-class. Segmentation-studio normalizes HRIS canonical fields; data-anonymizer makes the join safe under k-anonymity; calculus enriches the joined records into MetricEnvelope objects. The same envelope shape carries data from a Workday extract, a survey response, or a derived rollup — consumers don't care which.
  • 07Explicit contract versioning. Every spoke ships CONTRACT_VERSION; every additive change is a semver bump; every breaking change is a major bump with affected-consumer notes. Consumers vendor a copy and re-vendor on major bumps. The deploy boundary is clean.
Recent ships
  1. 2026-05-19TB-PRINCIPIA-01 + TB-PRINCIPIA-02: reserved principia-connector spoke namespace + optional Principia FK columns on four toolbox catalogs (chassis only; not flipped to live).
  2. 2026-05-18PAT-103/104/105: AI workforce trio (source-validation + conflict-detection + confidence-scoring agents) — drizzle/0054, three cron routes, three MCP tools.
  3. 2026-05-18PAT-113: Hub directive contract spec authored at docs/DIRECTIVES_HUB_CONTRACT.md (substrate-side of the directive contract meta-factory + vela vendor).
  4. 2026-05-18PAT-99-FU-A + PAT-96-FU-A: paid-leave evaluator + multi-currency display on wage-compliance (contract → 0.12.0).
  5. 2026-05-18PAT-46 + PAT-48: BLS + Census external-data connectors (lib pattern, 10 MCP tools, catalog flipped to "connected").
  6. 2026-05-18PAT-43-FU-A Tier 2 partial: visualization-catalog absorption — viz contract 0.2.0, 8 design-kit components, 5 new templates (15 total).
  7. 2026-05-18PAT-69 / F-4: LLM column matching for unmapped HRIS columns, wired to Vercel AI Gateway (segmentation-studio 2.2.0 → 2.3.0).
  8. 2026-05-18PAT-92 + PAT-93: Workday + BambooHR HRIS sync connectors (sync routes + MCP tools).
  9. 2026-05-18PAT-95 + PAT-94-FU-A: wage-compliance admin surfaces (conflict-resolution UI + review-queue UI).
  10. 2026-05-18PAT-102: jurisdiction-discovery AI agent (3rd toolbox AI consumer; discovery_candidates table; weekly cron).
  11. 2026-05-18PAT-96 + PAT-99: international statutory wage + paid-leave rule families (34 countries + 27 paid-leave jurisdictions; wc → 0.11.0).
  12. 2026-05-18PAT-98 + PAT-100: rule-family extensions for overtime + pay-transparency on wage-compliance (contract 0.9.0).
  13. 2026-05-18PAT-84-FU + PAT-95-FU: wage-compliance backend endpoint bundle (contract → 0.10.0 reconciled).
  14. 2026-05-18PAT-111: shared component primitives shipped (oklch tokens, /design/primitives showcase, marketing + metric-market refactored onto primitives via shim/adapter).
  15. 2026-05-17PAT-110 batch 1: multi-LLM deep-research ingest workflow scaffolding.
  16. 2026-05-16Wage-compliance fold: spoke wage-compliance shipped (PAT-79); jurisdictional rule families, refresh connectors, temporal diff agent.
In progress
  • ·Principia connector spoke: chassis reserved (TB-PRINCIPIA-01/02), but not yet flipped to live in the registry — heartbeat + contract types + MCP module + health route pending.
  • ·PAT-71 job-family-agent PA-fold: lift artifacts on disk under src/spokes/job-family-agent/{contracts,core,data}/, but missing heartbeat, db/schema.ts entries, API routes, withRouteLogger wrap, MCP module, TOOLBOX_SCHEMAS entry — Mike adjudicating finish-and-ship vs. discard-and-redispatch.
  • ·PAT-43-FU-A Tier 3+: Visualization catalog absorption follow-ups PAT-43-FU-A-2..6 (compensation strip, forecasting/time-series, distribution/scatter, composition, specialty templates).
  • ·PAT-89 / 89-B / 89-C: Rooftop precision phases — PostGIS + jurisdiction_geometry + point-in-polygon API, geocoding-provider abstraction, adaptive-precision investment rule (war-ready, deferred from wage-compliance MVP).
  • ·PAT-112 Brief 03: metric × segment workbench V0 → Cursor lift (V0 dispatch staged on Desktop; awaiting Mike's paste).
  • ·PAT-110 deep-research ingest: multi-LLM ingest workflow; batch 1 landed, remainder open.
Packageable components
ComponentStageReuse
Insight Card contract + sequencing core
src/lib/insight-player/
productionCross-spoke primitive; consumers vendor contract.ts + sequence.ts. Bump-via-toolbox is the only evolution path.
Contract registry
src/lib/contracts/
productionSingle source of truth on spoke contract versions; every spoke registers here.
MCP gateway + primitives
src/lib/mcp/ (+ src/app/api/mcp/)
productionStreamable HTTP + JSON-RPC; per-consumer auth, scope-restricted keys, fire-and-forget audit log. Used by all spokes.
Health roll-up
src/lib/health/
productionPer-spoke /health + aggregate /api/health.
Route logger
src/lib/log/route-logger.ts
productionWraps every route handler; emits one structured JSON line on completion keyed by canonical contract ID.
Service-key gate
src/lib/auth/service-key.ts
productionrequireServiceKey(request) POST gate; accepts x-toolbox-service-key and Authorization: Bearer.
AI gateway helper
src/lib/ai/getModel.ts
productionWraps Vercel AI Gateway for spoke-internal LLM calls. Used by PAT-69 column matching + PAT-86/102/103/104/105 AI consumers.
Connector pattern (DOL FLSA / BLS / Census / state-labor / HRIS)
src/lib/connectors/
productionLib-pattern connectors with refresh-policy abstraction. Available for reuse by other spokes.
Architecture

One repo, one Vercel project, one Supabase project, nine live logical services plus tier=N operator catalogs and two reserved-namespace spokes. The microservices boundary is logical, not physical: per-spoke API namespaces under `/api/spokes/<slug>/*`, per-spoke Postgres schemas pinned by `drizzle.config.ts` `schemaFilter`, per-spoke contracts in `src/spokes/<slug>/contracts/types.ts` that consumers vendor by copy. Cross-spoke internal imports are forbidden; the only sanctioned cross-spoke surface is another spoke's `contracts/types`. Two transports sit on top: HTTP JSON for engineers and MCP (Streamable HTTP + JSON-RPC) for AI agents, both audited per call into `mcp.mcp_audit`. Surfaces (toolbox-internal consumer UIs) live under `src/surfaces/<slug>/` and compose spokes via the same public APIs external consumers use — they get no privileged internal access. Drizzle migrations forward-only, auto-applied on production Vercel builds via `scripts/migrate-if-prod.mjs`, skipped on preview. The deploy boundary is the contract version: additive changes minor-bump, breaking changes major-bump with affected-consumer notes, and every consumer re-vendors on majors. Splitting any one spoke out into its own deploy later is a refactor, not a rewrite.

Outcome

Eight live spokes (reincarnation, preference-modeler, data-anonymizer, segmentation-studio, calculus, anycomp, forecasting, Conductor) plus one reserved namespace (job-family-agent) and a VoI capability lifted in 2026-05 (PAT-141, hosted at `src/lib/voi/` with a principia-prior adapter). MCP gateway + HTTP routes shared across the spoke set; all health endpoints green; mcp.mcp_audit writing real rows; database migrations auto-run on Vercel production builds. First external consumer (Performix) migrated to MCP transport 2026-05-11. **Chat-orchestration / MCP-gateway stack** shipped 2026-05 (PAT-N2/N7/N9 + follow-ups A–H): durable conversation history for `/admin`, SSE streaming admin chat turns, chat-turn → runPlan + composite adapter, HTTP-adapter method inference, intent-router catalog grounded to the live MCP registry, MCP gateway as primary dispatch (stateless — kills cross-lambda session-affinity flakes), plan-runner wizard pause-and-resume, durable `plan_runs` + deck-derived scout cards. **9 new spoke scouts** scaffolded (PAT-D1..D9: workforce-planning, survey-orchestrator, program-evaluation, network-analysis, factor-models, RBAC, ops-console, insight-sprint-studio, org-health-review) — README + SCOUT memo + contract sketch + queue entry per scout, ready for build dispatch. **Pay-fairness arc** (PAT-119) shipped contracts + scaffold + dispatch backlog (PAT-129..140) with invariants, threshold profiles, finding-maturity. HRIS / data-connector additions: Workday SOAP HRIS sync (PAT-65), Nationwide Census TIGER 2024 county + CBSA polygon seed via PostGIS (PAT-89-FU-A), industry-hinted worker-classification evaluator (PAT-97). Solo build.

The toolbox exists because every HR analytics product I worked with kept re-implementing the same five things — anonymization, metric definitions, segmentation, surveys, decision support — and getting each one slightly wrong. Building them once, well, and letting verticals consume them is the architectural bet. Two things changed in the last twelve months that sharpened the bet. The first was the narrowing decision: an earlier roster of broader spokes was cut down to seven that actually pull weight at production scale. The second was MCP. Once the algorithms can be called directly from AI agents — typed, scoped, audited — the toolbox is no longer a back-end someone else's UI sits on top of; it is the legible service substrate that both engineering teams and AI consumers compose against. Underneath all of that the original measurement bet is unchanged: HR analytics works only when behavioral science and statistical rigor are first-class. Constructs defined defensibly. Anonymity thresholds enforced in the contract, not in a settings page. Decisions getting value-of-information treatment rather than dashboard intuition. Small-N segmentations handled honestly rather than averaged into uselessness. The architecture is what makes one operator productive at the scale of a software company.

Architecture

Data plane — HRIS sources to privacy-gated cohorts.

Workday SOAP, OneModel, and the survey collectors all land in segmentation-studio's 35-field canonical map before anything downstream is allowed to look at them. Whatever the upstream system is, the records exit the normalizer in one shape — and then they hit the privacy gate. The gate is the load-bearing part. Min-N, k-anonymity, deterministic HMAC tokenization, and a substitution-strategy registry live inside data-anonymizer as a substrate primitive, not a settings page. Cohort-level rollups exist only because the gate is the thing every spoke that surfaces team-level results has to call before it returns. Below the floor, the answer is blocked — not averaged into uselessness.

Analytical spoke roster — eight live spokes with typed Zod contracts.

Eight spokes — reincarnation, preference-modeler, data-anonymizer, segmentation-studio, calculus, anycomp, forecasting, Conductor — each ships its own typed Zod contract and its own CONTRACT_VERSION. Algorithms live here; consumer apps vendor the contracts, not the code. The discipline is what makes the substrate-not-product posture executable. Adoption is spoke-by-spoke; there is no all-or-nothing migration. Additive changes are semver bumps. Breaking changes are major bumps with affected-consumer notes, and consumers re-vendor when they're ready.

MCP + HTTP gateway with chat-orchestration.

The MCP gateway is the primary dispatch. Stateless — which kills the cross-lambda session-affinity flakes that hounded the earlier in-process call shape — with per-consumer auth, scope-restricted keys, and a fire-and-forget audit row per tool call landing in `mcp.mcp_audit`. Any AI agent calls any spoke without bespoke integration. The HTTP routes are parallel transport for engineering teams; same algorithms, different shape. The chat-orchestration stack sits on top — durable conversation history, SSE-streamed admin chat, chat-turn into runPlan via the composite adapter, an intent-router catalog grounded to the live MCP registry. That's the substantive new orchestration capability of the hub. It's what makes AI-native legible: one operator, productive at the scale of a software company.

Consumer flow — typed-contract composition across the portfolio fleet.

Performix migrated to MCP transport on 2026-05-11 as the first external consumer — vendoring reincarnation, data-anonymizer, segmentation-studio, and calculus contracts rather than re-implementing the algorithms. DevPlane sits on the wildcard key for operator coordination. Vela and PA-site consume against the same gateway. Future products extend the fleet via the same contract-vendoring pattern — there is no other shape. Two things are doing work here, and the analytics discipline gets understated when the architecture story takes the foreground. The architecture is what makes solo-operator multi-product cadence possible. The analytical discipline — protected feedback, honest small-N CIs, construct-grounded codegen, value-of-information rather than dashboard intuition — is what makes the substrate worth trusting at all.

Surfaces
Landing — typed-contract service substrate; 79 MCP tools across 10 spokes.

Landing — typed-contract service substrate; 79 MCP tools across 10 spokes.