Made-up companyAI-drafted · 20 logged model calls

Variance analysis and automation

Month-end variance commentary, automated

A month-end close pipeline for Tillbrook Software, the made-up company from the headcount plan. It works out every department's variance against plan, a language model drafts the commentary for each material one, and automated checks tie every draft back to the ledger. The checks sent back 1 of 19 drafts: the model had called a commission timing adjustment persistent, which would have added $544,730 to the full-year forecast.

The June 2027 month-end variance pack in the browser: the summary against plan, the material variances with the model's commentary, owner, next step and reforecast impact.

The month-end pack

Pick a month. The pack has the summary against plan, every material variance with the model's commentary, owner, next step and reforecast impact, and the reforecast. The second tab shows the draft the checks sent back and the draft that replaced it; the third scores the commentary against the causes planted in the books.

Download the six packs · 27 KB
Tillbrook Software · month-end close 2027made-up company
5 material · all drafts passed the checks

June 2027 against the FY2027 plan

Variance = actual − plan. For cost lines + is over plan.
JunePlanActualVarianceYTD planYTD actualYTD variance
Revenue$9.23m$9.21m−$11.2k$52.41m$52.36m−$48.5k
R&D$2.92m$2.76m−$159.6k$16.35m$15.69m−$652.3k
Sales$2.05m$2.06m+$5.5k$11.70m$11.69m−$12.6k
Marketing$1.42m$1.48m+$67.3k$8.38m$8.60m+$218.6k
Customer success and support (cost of revenue)$2.02m$2.06m+$44.2k$11.56m$11.68m+$119.0k
G&A$1.41m$1.44m+$36.9k$8.50m$8.66m+$160.6k
Total cost$9.82m$9.81m−$5.7k$56.48m$56.32m−$166.6k
Operating income−$0.59m−$0.60m−$5.5k−$4.08m−$3.96m+$118.0k

Material variances and the model's commentary

Largest first, by the variance that made it material

G&A · Professional fees and other G&A

+$3.2k in Jun (+1.3% of plan)·+$229.4k year to datematerial on the year to date

One-time

Professional fees and other G&A is $229,376.83 over plan year to date (actual $1,729,376.83 vs. plan $1,500,000.00, 15.3%). The overage is driven by a one-time $210,000.00 Brandt & Okafor LLP invoice (INV 5531) booked in May, so the variance is one-time with no FY2027 reforecast impact. June alone was $3,217.07 over plan (1.3%) with no non-routine items.

Owner
Controller
Next step
The Controller obtains the Brandt & Okafor LLP engagement letter and scope for INV 5531 to confirm the $210,000.00 is non-recurring and that no further billings are due in FY2027.
Reforecast impact
None for the rest of the year
Evidence cited
E-00242 · E-00287 · E-00288 · E-00289 · E-00290

R&D · Salaries and benefits

−$133.0k in Jun (−5.5% of plan)·−$533.2k year to date

Persistent

R&D Salaries and benefits was $132,971.54 under plan in June 2027 (actual $2,267,053.13 vs. plan $2,400,024.67, -5.5%), a favorable variance. The variance is persistent: June paid FTE was 97.9 against 104.9 planned, as YTD hires of 13.4 trailed the 20.4 plan while leavers matched plan, partly offset by average monthly salary per FTE of 18,569 versus 18,351 planned. Because it is persistent, the June variance carries into each of the six remaining FY2027 months in the reforecast.

Owner
VP Engineering
Next step
VP Engineering confirms the open-requisition pipeline and start dates that close the gap to the 104.9 FTE plan and explains the higher average salary per paid FTE before the reforecast is locked.
Reforecast impact
−$797,829 for the rest of FY2027
Evidence cited
E-00244 · E-00245 · S-RD-HEADS-06 · S-RD-PAY-06 · S-RD-HIRES-YTD-06 · S-RD-LEAVERS-YTD-06

Customer success and support · Cloud hosting (cost of revenue)

+$128.9k in Jun (+12.7% of plan)·+$371.5k year to date

Persistent

Cloud hosting (cost of revenue) was $128,894.92 over plan in June 2027 (actual $1,143,653.91 against plan $1,014,758.99), an unfavorable variance of 12.7%. The overage is volume-driven: compute-hours were 1,429,567 against a plan of 1,268,449 at an unchanged price of 0.8 per hour, and the Nimbus usage charge has been above plan since March. The variance is persistent and is expected to repeat in each of the six remaining months of FY2027.

Owner
Head of Infrastructure
Next step
Pull the June Nimbus Cloud usage breakdown to identify which workloads drove the extra compute-hours, confirm whether the load is sustained, and update the FY2027 hosting reforecast for the remaining months.
Reforecast impact
$773,370 for the rest of FY2027
Evidence cited
E-00285 · S-HOSTING-HOURS-06 · S-HOSTING-RATE-06

Customer success and support · Salaries and benefits

−$73.5k in Jun (−9.3% of plan)·−$215.5k year to date

Persistent

June salaries and benefits came in $73,527.67 under plan (-9.3%). The shortfall is driven by paid headcount of 59.6 against a plan of 65.6, as leavers reached 14.2 year-to-date versus 4.2 planned. The variance is persistent and is expected to continue through the 6 remaining months of FY2027.

Owner
VP Customer Success
Next step
Confirm the June paid FTE gap (59.6 vs 65.6) and backfill timing with HR, and reconcile the year-to-date net hiring shortfall (about 8 heads) to that 6-FTE gap, since the reforecast assumes the gap persists for the 6 remaining months.
Reforecast impact
−$441,166 for the rest of FY2027
Evidence cited
E-00266 · E-00267 · E-00268 · S-CS-HEADS-06 · S-CS-LEAVERS-06 · S-CS-LEAVERS-YTD-06 · S-CS-HIRES-YTD-06 · S-CS-PAY-06

Marketing · Marketing programs

+$68.8k in Jun (+9.8% of plan)·+$212.8k year to date

Persistent

Marketing programs is $68,824.66 over plan in June (actual $768,824.66 against plan $700,000.00, 9.8% over), and $212,817.03 over plan year to date. The overrun is persistent, driven by a recurring Halvorsen Data invoice of $207,000.00 that has been flat since March after running at $150,000.00 in January and February. Because the variance recurs, it is expected to repeat in each of the 6 remaining FY2027 months at the June amount unless the vendor rate is renegotiated.

Owner
Marketing operations lead
Next step
Confirm whether the FY2027 plan assumed the $150,000.00 Halvorsen run-rate, review the $207,000.00 invoice against the contract rate, and report back to the Controller before the July close.
Reforecast impact
$412,948 for the rest of FY2027
Evidence cited
E-00281 · E-00282 · E-00283 · E-00284

FY2027 reforecast after the June close

Plan + year-to-date variance + persistent variances repeated for the months left
FY2027PlanReforecastChange
Revenue$112.47m$112.42m−$48.5k
Total cost$117.88m$117.66m−$219.2k
Operating income−$5.41m−$5.24m+$170.7k

Cost change = −$166.6k already spent against plan this year, and −$52.7k from 4 persistent variances repeated for the 6 months left: R&D salaries and benefits −$797.8k, Customer success and support cloud hosting (cost of revenue) +$773.4k, Customer success and support salaries and benefits −$441.2k, Marketing marketing programs +$412.9k. One-time and timing variances add nothing for the rest of the year.

How it was built. I built it with an AI agent system I run. It wrote the pipeline to my brief, I went through it myself, and a separate check re-derives its figures from the source data. Inside the pipeline, a language model (claude-haiku-5-5, called through the Claude Code command line) drafts every commentary, and automated checks tie each draft to the ledger before it goes into the pack. Tillbrook Software is made up; its plan is the FY2027 headcount plan on this site, and its ledger was generated with eight causes of variance planted in it.

The audit trail in the browser: a model draft the checks sent back, with the problem each check found, next to the draft that passed.
The one draft the checks sent back. The ledger had a $72,000 accrual adjustment for three March deals; the model labelled the April overrun persistent and repeated it for eight months. The label check and the reforecast check both failed it, and the next draft called it timing, with no further impact.
The scorecard in the browser: the final commentary against the answer key of planted causes.
Scored against the answer key: the right main cause on 19 of 19 material variances, 19 of 19 labels right after the checks (18 before), and the second, smaller cause behind three R&D variances named in 3 of 3.
The FY2027 headcount plan running in the browser: sliders for hiring delay, attrition and quota attainment, heads by department through 2027, and the plan against its opex targets.
The plan the actuals run against is the FY2027 headcount and opex plan for the same made-up company, as its memo recommends approving it.

The full analysis

Each part opens on click.

How the pipeline works291 journal lines · 35 department lines · 19 material variances · 20 model calls

Plan

The FY2027 plan by department, line and month, from the headcount plan's own engine (the case its memo recommends). It ties to that plan's P&L.

Actuals

A made-up ledger for January to June 2027: 291 journal lines with a vendor, a short memo and an entry type, the way a ledger looks, plus HR, CRM and cloud statistics. Eight causes are planted in it, on top of random noise: late hiring, attrition, a pay rise above plan, a vendor price increase, a one-time legal bill, cloud usage, a commission cut-off and an annual licence expensed instead of prepaid. The true causes are in an answer key that only the scorer reads.

Variances

Month and year-to-date variance for each of 35 department lines, the materiality rule, and the pipeline's own one-time / timing / persistent label and reforecast impact, both from written rules.

Drafts

One real model call per material variance through the Claude Code command line (claude-haiku-5-5, no tools, a fixed system prompt). The model gets the numbers, the department's whole month in the ledger and its statistics with ids, the rules, the owner list and a list of reason codes, and returns the cause, label, owner, next step, reforecast impact and commentary as JSON. Every prompt and reply is logged with the model's name, the usage and a timestamp. Cap: 80 calls a run, 3 drafts per variance; if a call fails, the run stops and the pack is not built from templates.

Checks

Nine checks on every draft. A flagged draft goes back to the model with the problems written out, and the trail keeps the draft, the flags and the next draft.

Score

The final commentary and, for comparison, the first drafts against the answer key: main causes found, second causes named, causes invented, labels right.

The rulesWritten once; the prompt, the checks and the pack all use the same text

Sign. Variance = actual minus plan. For costs a positive variance is over plan (unfavorable) and a negative one is under plan (favorable).

Materiality. A variance is material when, for one department and report line, the month's variance is at least $50,000 and at least 5% of that month's plan, or the year-to-date variance is at least $150,000 and at least 3% of the year-to-date plan.

One-time, timing or persistent. Timing: this month the line has an entry that books something to another period and will reverse (an accrual adjustment for an earlier month, a reclass between expense and prepaid, or an invoice for a service period longer than a month posted straight to expense), or, for commissions, the month's accrual was calculated on new ARR more than 5% away from the new ARR booked in the CRM that month. One-time: not timing, and the line has an invoice this month (or, for a year-to-date variance, earlier this year) from a vendor not seen on this line before in the year, at least half the size of the variance and in the same direction. Persistent: everything else (headcount, a recurring vendor's rate, usage).

Reforecast. Persistent: this month's variance repeats in each remaining month of FY2027, so the full-year impact on cost is this month's variance times the number of months left in the year (6 after June, for example). One-time and timing: no further impact (zero) on the remaining months.

What the checks caught1 of 19 drafts sent back; word for word from the log

April, sales commissions. The month's ledger had a $72,000 commission accrual adjustment for three deals, with the entry type “accrual adjustment”. The model read it as a cost that will repeat, labelled the variance persistent and carried $544,730 into the rest of the year. Left in, that would have overstated FY2027 cost by the same amount.

Draft 1 (model call 7): Commissions are $68,091.30 over plan for April ($275,552.70 actual vs $207,461.40 plan, 32.8%), an unfavorable variance. The overage comes from a $72,000 commission accrual adjustment on SO-1187, SO-1191 and SO-1192, partly offset by the base accrual calculated on new ARR of $2,035,500 against $2,074,600 planned. The line is classified as persistent, with the adjustment's basis still to be confirmed by Sales Operations.

C6 label: labelled persistent, but the written rule says timing: the line has an entry that books to another period (E-00183) · C7 reforecast: reforecast impact $544,730, but the rule gives timing: no further impact, $0

Draft 2 (model call 8): Commissions are $68,091.30 over plan for April ($275,552.70 actual vs $207,461.40 plan, 32.8%), an unfavorable variance. The overage is driven by a $72,000.00 commission accrual adjustment on SO-1187, SO-1191 and SO-1192, while the base accrual of $203,552.70 was calculated on new ARR of $2,035,500, matching the CRM booking. The line is classified as timing, so the reforecast impact is zero, pending Sales Operations confirmation that the adjustment reverses.

CheckWhat it testsFlags in the pack's run
C1 formatThe reply is one JSON object with every field: reason code, cause, evidence, label, owner, next step, reforecast impact, commentary.0
C2 numbersEvery number in the commentary, cause and next step ties to the plan, the ledger, the statistics, the written rules or the pipeline's own results, within the precision it is written to.0
C3 states the varianceThe commentary states the variance it is about.0
C4 directionThe first sentence's over / under wording matches the sign of the variance.0
C5 owner and next stepThe owner is on that line's owner list, and there is a next step of at least six words.0
C6 labelThe one-time / timing / persistent label agrees with the written rule, which the pipeline applies to the ledger itself.1
C7 reforecastThe reforecast impact agrees with the written rule.1
C8 evidence and causesEvery cited id is in the evidence, and every cause the text asserts (late hiring, attrition, pay, a price change, usage, legal work, a cut-off, a prepaid, or anything else) is backed by it.0
C9 pack wordingThe commentary and the next step are written for the reader of the pack: no field or type names, statistic ids or talk of the pipeline's tests and codes.0

Each check is also fed a known-bad draft and has to go red, and fed the phrases it once got wrong and has to stay quiet: 23 of 23 selftest cases behave as expected.

What the checks did not catchThe score against the answer key finds what a mechanical check cannot

The checks only test what can be tested against the books. In the final run the score against the answer key found nothing they let through: every main cause and every second cause was named, and no cause was invented. The previous version of the test, in the call log, shows what they miss. Its May R&D commentary explained the shortfall by late hiring and left out the smaller cause on the same line, pay per head above plan after the April merit round; every number in it was right, so no check could object. Its low-effort run listed a half-percent difference in support pay per head among the reasons: a real figure, so it passed, but in the books it is noise.

That version also had a problem the pipeline created itself. Its prompt rounded the plan, the actual and the variance to the dollar one by one, so the figures it showed did not subtract ($275,553 − $207,461 is $68,092; the variance shown was $68,091). The fixed April draft then told Sales operations to resolve a $1 gap that is not in the books, and no check could see it, because the checks compare the text with the ledger, not with the prompt. The prompt now shows every figure to the cent, every draft was redone, and a ninth check sends back commentary in the pipeline's own words (that same next step had cited an entry's “accrual_adjustment type”).

So the checks hold the numbers, labels and reforecast to the ledger and the written rules; they do not judge what matters, and they cannot catch a mistake built into what the pipeline hands the model. That is why the score exists here, and why a real close still needs a person who knows the business to read the pack.

The same prompts at a cheaper settingDefault effort: $3.23 for 20 calls · low effort: $1.50 for 20

The pack comes from the command line's default setting, where the model reasons before it answers. The same 19 prompts were also run with --effort low, which skips that step and cost about 46% as much per call.

Default effort (the pack)Low effort
First drafts that passed every check18 of 1918 of 19
Right main cause, final19 of 1919 of 19
Labels right, first drafts18 of 1918 of 19
Second cause named3 of 33 of 3
Causes invented, final00
Cost of the calls used$3.23$1.50

On this ledger the two settings ended up the same. Both made the same April mistake, labelling the commission catch-up persistent, and both fixed it when the checks sent it back; the low-effort draft also talked about the pipeline's “timing or one-time tests”, which the wording check caught. One run each is too few to say which setting is better in general.

What the checks got wrong22 false alarms while the checks were being built, all fixed

Across the 142 model calls made for this project ($17.10 in all), earlier versions of the checks sent back 22 drafts that were right. The cause check read “the price held at $0.80”, “leavers matched plan” and “average pay per FTE was close to plan” as claims that those things caused the variance, read the law firm Marlow Price LLP as a claim about price, and read a sentence saying it was not yet known whether a change was rate or volume as a claim about volume. The number check took the “-31” out of a date, did not know the 5% threshold quoted from the written rule, and was stricter than the books on rounding. Every fix is now a selftest case, and the call log keeps each false alarm: the re-draft prompts quote the flags as they were sent.

The first version of the test was also too easy. It gave the model one ledger line at a time, with memos that spelled out the cause: that a contract had renewed at a new list rate, which deals the commission cut-off had left out. In the default run every first draft named the right cause, and across both settings the checks found nothing beyond a stray $1 rounding figure, so the test could not show anything. The second version gave it the department's whole month with short memos, the way a ledger looks, and mixed a second cause into three lines; the final version keeps that and fixes the rounding in the prompt described above. All three versions are in the call log.

Limits

Tillbrook is made up, and so is its ledger: the planted causes are cleaner than real ones, and the statistics a real team would have to chase are all at hand. The checks test what can be tested mechanically; they cannot tell whether a next step is a good one, or whether a cause the evidence supports is the main one. The score against the answer key is how this demo measures that, and a real close has no answer key. The reforecast rule is deliberately simple: a persistent variance repeats at this month's size. Revenue has no planted cause. One model and one run per setting: another run would draft differently, which is why every prompt and reply is logged.

Files