The FY2025 one-pager for the CFO is written to `output/exec-summary.md`. The figures come from the summary script, saved in `output/summary.json`. Its checks passed: the four quarters add up to full-year revenue, operating income matches when rebuilt from the individual lines, and December revenue in the KPI file matches the P&L.

**Headline:** FY2025 revenue was $11.2M against a budget of $11.6M, and operating income was $388K against $583K.

- **Results:** revenue missed budget by ($362K) and operating income by ($195K). Gross margin was 25.9% against a budget of 26.8%, (0.9) points under. Operating expenses came in on budget, missing by only ($649).
- **Quarters:** revenue fell short of budget in all four quarters. The largest misses were Q1 at ($121K) and Q3 at ($229K).
- **Drivers:** the main unfavourable line is Revenue at ($362K). Cost of goods sold came in $196K under budget, which absorbed part of the revenue shortfall. Salaries and wages ran ($38K) over, offset by savings in Marketing and Technology.
- **Watch list:**
  - Days sales outstanding was 51.2 days against a target of 45.0, off target for 3 months.
  - On-time delivery was 93.3% against 95.0%, off target for 3 months.
  - Active customers were 40 against 42, off target for 2 months.

I left Inventory turns off the watch list, although it is also off target at 5.33 against 6.50. It has only missed for one month, so it didn't seem to need the CFO's attention yet. Tell me if you want it added.

The data doesn't show why revenue missed. A customer-level revenue file would answer that, and the summary says so instead of guessing at a cause.