Orahovo Furniture Group is a fictional regional furniture manufacturer with entities in
Serbia, Croatia and Bosnia and Herzegovina, four product lines and five years of monthly actuals and budgets.
Every figure is generated from a fixed seed (20260908), so anyone can regenerate it and confirm none of it
is real. I use it to show how I work, one stage at a time.
Data
Proves: data engineering, governance
Everything on this page is computed from one synthetic dataset. It is generated from a fixed seed, so anyone
can regenerate it and confirm that none of it comes from a real company. This section describes what the
dataset is and how it was made; the planning, forecast and explanation stages below read it through the API.
Plain words
This is where the numbers come from. Three companies keep their books a little differently, so the first job is to read all three and put them into one shape. Then I add up what was loaded and compare it with totals written down before loading. If both agree to the cent, the rest of the site can be trusted.
What it is
Loading the dataset description…
Why it is provably synthetic
Every figure is generated from seed 20260908, with the economic story written into the generator: an energy cost spike in 2022–23, price increases in 2023 and 2025, a supply disruption in Bosnia in mid-2024, a Croatian sales campaign in late 2025, and wage indexation every January. Budgets are built each year from the previous year's actuals with fixed uplifts.
What the raw extracts get wrong
The generator also writes deliberately dirty source files: three ledgers in three formats, duplicate postings, blank cost centres, a renamed cost centre, Croatian headers, comma decimals, a currency switch from kuna to euro, zero-padded account codes and a wide budget file. A loader rebuilds the clean schema from those files and reconciles it to control totals when the site is built.
This is an overview of the dataset. The reconciliation runs during the build; it is not an interactive view on this page.
Pick an entity and a month. The P&L shows budget, actual and variance; the bridge walks from budget to
actual through volume, price, unit cost, fixed cost and FX and must reconcile exactly; the cost-centre view
shows FTE by cost centre next to the fixed-cost lines; the group view adds the intercompany elimination and a
per-entity table. Everything on this panel comes from the API, nothing is typed into the page.
Plain words
A budget is a promise about the year; the actual is what happened. The bridge splits the difference into reasons: we sold more or fewer pieces, at higher or lower prices, each piece cost more or less to make, the fixed bills changed, and the exchange rate moved. The reasons add up to the whole difference, which is how you know nothing is missing.
Loading from /api/company/…
P&L, EUR
Bridge: budget → actual operating result, EUR
…
Cost centres and fixed cost
Group view: elimination and entities
Amounts are EUR at the actual monthly rate. The API returns entity results in EUR only; the local currency is shown as its code.
Definitions
Forecast
Proves: financial forecasting
Monthly group revenue since 2022 with the last six months held out. Three models are fitted on the training
window only and compared on that holdout: seasonal naive, seasonal with growth, and Holt-Winters. The
benchmark must be beaten to justify the model. The best model's next six months, plus the last three months'
prices, unit costs and fixed cost, form the baseline that the sliders below adjust.
Plain words
A forecast is a guess with a method. The simplest guess is the same month last year, and a model must beat that to earn its place. I hide the last six months, let each method guess them, and measure which came closest. The sliders then show what happens to the next half-year if volume, price or cost move.
Loading from /api/forecast
Group revenue, EUR, actual and forecast
Holdout: the last six months, three models
Backtest metrics
Method
Scenario on the next six months
…
Formulas (the same as the API's bridge, applied per product line and month)volume = (units_s − units_b) × (price_b − unit_cost_b)
price = (price_s − price_b) × units_s
unit_cost = −(unit_cost_s − unit_cost_b) × units_s
fixed = −(fixed_s − fixed_b) (the sliders leave fixed cost unchanged)
fx = 0 (the baseline is already in EUR)
check = result_s − result_b − (volume + price + unit_cost + fixed + fx) → must be 0 before rounding
Ask why the result is below budget. The numbers are computed in Python; the model only puts them into words
in one bounded call, and the answer is checked against those numbers before anything is shown. Every step
appears in the trace with its status and timing, including answers that were rejected. It works with and
without a model key; the template mode is always available and is labelled as such.
Plain words
The computer works out the numbers; the language model only puts them into sentences. Before you see an answer, every number in it is checked against the list of allowed numbers. If the model made one up, the answer is rejected and you can see that it was. A plain written template is always there as the fallback.
…
Rejected by the contract check
Metrics used
Trace
Usage: loading from /api/explain/usage
How this stage is built
Validate the request, compute every number in code, make one bounded model call with those
numbers and a JSON contract, check that nothing in the answer is outside the fact pack, then present it with
its trace. A rejected answer is shown as rejected, not hidden, and the deterministic template takes its place.
The only paid call is this one, capped per day and cached per question.
Teach
Proves: training and coaching
The Plain words toggle in the header adds a short explanation under every stage, written for someone
who has never read a variance bridge. Below is the exercise I would give a planning team on these numbers.
Teaching is shown here as a skill, not sold as a service.
Plain words
Every stage above now has a panel like this one. Read the panel first, then the numbers. When the numbers make sense without the panel, switch it off.
Exercise: change a driver, read the bridge, explain what moved in one sentence.
Go to the Forecast stage, move only the Volume slider to +10%, and read the bridge from baseline to
scenario. Write one sentence that says what moved and why, using the words volume, price, unit cost and fixed cost.
Reveal the model answer and the questions for the planning conversation
Model answer. Only the volume effect moves: the extra units earn the baseline contribution per unit, price
and unit cost per piece are unchanged, and fixed cost does not react to volume, so the operating result improves
by exactly the volume effect.
Four questions for the planning conversation.
Which of the five effects did we decide, and which happened to us?
Is the price effect a real price change, or a mix shift towards dearer products?
Will the unit-cost effect repeat next month, or was it a one-off?
Which budget assumption would have to change to close the gap, and who owns it?
That is how I structure teaching: one explanation in plain words, one exercise on the real numbers, then
the questions that turn it into a discussion.
Agents
Every job I run reports back here when it finishes. The board reads /api/status; jobs
post to /api/report with a token.
How jobs report to this board
A scheduled script recomputes the forecast and posts its status and metrics to the board's
reporting endpoint with a token. Board state lives in the container's file system and resets on every
redeploy; entries return as each job next runs.