Test project8 Jul 2026
vulpecula - «Косвенно», a Bayesian inference console built for an AI-first design-studio test task

- React 19
- TypeScript
- Vite
- Tailwind CSS 4
- Zustand
- Bayesian inference
- Vitest
- Accessible
A test task for a design studio hiring an AI-first developer: build an interactive mini-app around one of two probabilistic scenarios - an invisible-rabbit farm or a fox dispatcher - with editable data, a live-recomputed report, and an in-app AI worklog. I built both scenarios plus a third (a capture-recapture bug estimator) on ONE shared engine, because the interesting claim is not the rabbit arithmetic but the architecture: nothing under the component tree may name a scenario - components dispatch on data shapes (scene kinds, explanation kinds), scenarios are plain descriptors (schema, seed, params, report function), and a new scenario adds zero component code. The math is a zero-dependency Bayesian core - discrete posteriors over a hypothesis grid, Poisson likelihoods, log-sum-exp stabilised, with credible intervals, per-record leave-one-out attribution and per-feature log-odds decomposition - and the UI's own rule is that every number on screen is derived from the model, never typed in. The instrument itself: an editable record table (custom listboxes, a two-column time picker, auto-clamped numeric cells with footnoted validation), a posterior histogram with an HDI band, area-proportional scene bubbles, a nomogram for the fox, counterfactual attribution bars, plain-language [почему?] panels that show the arithmetic behind every headline number, a pinned-baseline diff mode, permalinks encoding the full state in the URL hash, a change journal whose rows say exactly what changed (запись 1 · Сила сигнала: 4 → 10) and restore on click, JSON export with preview, and a scripted 40-second tour that runs on its own page without touching your working state. The AI worklog - a MOX requirement - is first-class: checkpoints where AI proposals were rejected or modified, each with the reasoning and a measured comparison (e.g. a batch scoring signature rejected because it makes leave-one-out O(T²·K) instead of O(T·K), verified on a spike branch). Determinism is enforced (no Math.random, no Date.now in the app), Safari's history.replaceState throttling is respected via discrete commit boundaries, and ~1100 unit tests pin everything from the engine's exchangeability to the Russian copy, character for character. React 19 + TypeScript + Vite + Tailwind 4 + Zustand + Motion, deployed on Cloudflare Pages.