whats-changed · git:20260925.ba78503 · 2026-09-25 · sha256 9f118a119430ae3b
whats-changed git:20260925.ba78503A
Immutable. This exact content never changes and is served at /api/v1/blob/9f118a119430ae3b.
--- name: whats-changed description: Compare two periods of the same report and say what moved, by how much, and which few lines explain the total — ranked, with rate split from volume. Use when the user has this month's and last month's numbers (workbook, CSV, PowerPoint pack, PDF or Word doc) and asks what changed, what's driving it, why revenue or cost moved, or wants month-on-month or quarter-on-quarter variance commentary they can repeat in a meeting. Not a cell-by-cell diff, and it never invents a cause the source doesn't state. --- # What's changed Every reporting pack answers *what the number is*. Nobody ships the paragraph that says **what moved, by how much, and which two lines account for most of it.** That paragraph is what gets asked for in the meeting. **The product is the ranking, and the discipline is not explaining.** Of the forty things that moved, name the few that explain the total, say plainly that the rest is noise, and **never supply a cause the source does not state.** A report that says "down on seasonal softness" is worse than useless — it puts a fabricated cause into someone's mouth in a standup. ## Workflow ### 1. Take both periods as given Two files — prior and current — or one file with two period columns. Accepts `.xlsx`, `.xlsm`, `.csv`, `.tsv`, `.pptx`, `.pdf`, `.docx`, or text pasted into chat. **Mixed pairs are normal and supported**: an August PDF against a September workbook is what the user has to hand, because the workbook stayed with whoever built it. Infer which is the earlier period from filenames, sheet or slide titles, or a date header. **Ask nothing unless genuinely blocked.** At most two questions, and only these: - Which period is earlier genuinely cannot be inferred → *"Which of these is the prior period?"* - No shared key exists, so rows cannot be matched at all → say what each source is keyed on, ask how to align them. Never ask about format, audience, thresholds, or how much detail they want. Draft first. ### 2. Extract before comparing Read `references/extraction.md` and follow it. It covers per-format fidelity, the flat intermediate every source reduces to, mandatory source locators, and the four rules that stop a deck or a PDF producing confident nonsense: - never read a number off a **chart image**; - never **OCR** into the output without flagging it; - compare at the **coarser precision** of the two sources; - a line a truncated source didn't show is **not disclosed**, not gone. The precision rule is the one that bites. A deck at `£1.8m` against a workbook at `£1,783.2k` is not a £16.8k movement — it is rounding, and reporting it is a fabrication that looks like arithmetic. ### 3. Align rows, then compute Match on normalised label, then on position. Compute per line: prior, current, change, and — where the source carries both a count and a value — the **rate/volume split**. Whether a total moved because units moved or because the per-unit figure moved is the most useful thing this skill can say, and it is pure arithmetic. Reconcile before reporting: **the sum of the rows is the truth**, not a total the source prints. If they disagree, the gap is a flag. If the source is truncated and there is no complete set of rows to sum, `materiality.md` ranks the candidate totals by how checkable they are — a printed total comes last. ### 4. Rank, and drop what doesn't qualify Read `references/materiality.md` and apply its two gates. They are numeric on purpose — "report what matters" drifts from run to run, two thresholds don't. Everything failing both gates aggregates into one `all other movements` row, never silently dropped, so the arithmetic still closes. The reference also carries the refuse-to-say table, the rulings for new and gone rows, renames, sign flips and unit changes, and the closed ten-item list of what earns a flag. Those cases are the skill; do not improvise them. ### 5. Write it and stop A headline, then the tables, then the fixed trace line. No preamble, no methodology section, no offer of further analysis — the working is available on request, not printed. ```markdown **Cost of service rose £41.2k (+6.8%) to £647.9k.** One line explains four fifths of it. Read from `oct-pack.pptx` (slide 4 table) against `sep-costs.xlsx` (Costs tab). The deck rounds to £0.1k, so smaller movements aren't visible. ## Drivers (ranked) | # | Line | Prior | Current | Change | % of total move | Note | |---|------|-------|---------|--------|-----------------|------| | 1 | Hosting — EU West | 118.4 | 151.6 | +33.2 | 81% | Instances +28%, unit price flat | | 2 | Support — outsourced | 96.0 | 105.3 | +9.3 | 23% | Rate +10%, volume flat; "new MSA rate from 1 Oct" per slide 4's note | | 3 | Licences | 84.2 | 79.1 | −5.1 | −12% | Seats −6% | | 4 | Observability | — | 6.8 | +6.8 | 17% | new line | | | all other movements (7 rows) | 246.1 | 243.2 | −2.9 | −7% | none individually material | ## Structural changes (2) - S1 `Observability` is new this month — £6.8k, no prior comparative. - S2 `Legacy monitoring` has gone; it was £5.4k last month. It may have been absorbed into `Observability`, but nothing in either source says so. ## Flags (3) - F1 The Costs tab totals £650.5k; the rows sum to £647.9k. £2.6k unaccounted. - F2 `E22` is a typed-in number, not part of the column formula — which is why that total doesn't reconcile. - F3 Slide 6 carries the regional split as a picture, not a chart. Those numbers weren't readable; the underlying file is needed if that split matters. Ask "how did you get £41.2k?" or "why is #2 a driver?" to see the rows and arithmetic behind any figure. ``` Note the first two flags: one typed-over cell fires two triggers — the total not reconciling, and the hardcoded cell — so it earns **two lines, not one.** Count triggers, not defects. `% of total move` is signed against the total's direction, so an offsetting line shows negative. That is information, not a bug — which is why the column is not called `% share`. ## Rules - **Never invent a cause.** Arithmetic is yours to state; causation is not. The only permitted causal language is **quoted from the source** — a note column, a footnote, a variance-reason field, a deck's commentary — and attributed to it. Everything else is movement described, not explained. - **Every clause in the headline is checkable against the table.** The second sentence is where arithmetic-free wording creeps in — "roughly cancel out", "broadly offset", "mixed picture". Say it in the table's own quantities instead: *"one line explains four fifths of it"*, *"Nordics and DACH offset about a third"*. Before writing it, add up the lines the sentence names and check the words match the sum: lines netting +20 against a −59 fall **offset a third**, they do not cancel. If no short true phrasing exists, keep the first sentence and drop the second. - **Rank or don't report.** An unranked list of everything that changed is the problem the workbook already has. If the drivers can't be ranked, say why. - **Flat is a valid answer.** When the total moves less than 1%, the absolute gate switches to 1% of the prior total (`materiality.md` §1) — otherwise noise clears it. *"Revenue is flat within 1%; no line moved more than £3k"* is true and useful. Never manufacture drivers to fill the table. - **Say less than you were asked for when the source can't support more.** A coarse PDF against a fine workbook yields a thin report; that is the honest output. - **No growth rate on a new row, a gone row, or a move across zero** — there is no denominator. Write `new`, `gone`, or describe the flip in words; never `∞`, never `340%` on a £40 base, never `n/a%`. `% of total move` is a different quantity and **does** apply to those rows; it is what makes the table's arithmetic close. - **The rows are the truth.** Never repeat a printed total that its own rows contradict. When a source is truncated and there are no complete rows to sum, prefer a total you can derive and cross-check — a segment chart's parts, say — over the printed one, say which you used, and flag the disagreement. A printed total is a claim, not evidence, however prominent. - **Cite a locator** for every figure whenever either source is not a spreadsheet. `Revenue!E7`, `slide 6, table row 3`, `p.12 Table 4`. Nobody can eyeball a diff of two PDFs. - **Flags are a closed list.** Only the ten triggers in the reference earn a line, one line per trigger **even when two triggers share one root cause** — a typed-over total cell is two flags, not one. Risks, opinions, things that merely seemed notable, and limitations of your own analysis are commentary. Omit the section when nothing qualifies. - **Stop and flag on a unit or currency mismatch** between the two sources. Every number would otherwise be wrong by 1000×. This is the one case worth refusing to report on. - **Output lands in chat** as copyable markdown. Write a file only if asked. Don't offer to chart it — the user has minutes before a meeting and wants sentences. ## Tracing The output is repeated in meetings, so every figure in it will be questioned once. Read `references/tracing.md` before answering any follow-up: it carries the handles (`headline`, `#1…`, `other`, `S`, `F`), the fixed closing line — whose example figure is the headline's own change — the trace block (*Rows · Arithmetic · Why it's here · What would change it*), and the questions to expect: *"your total doesn't match the pack"*, *"why isn't this 200% line in there?"*, *"is it price or volume?"*, and above all *"why did it go down?"* — which gets only what the source states, quoted, or *"neither source gives a reason"*. A trace recomputes from the sources by locator and **corrects the output** if the numbers don't reproduce.