Three grades of citation
The useful measure of a citation is how much reading it takes to falsify. A citation you cannot cheaply falsify is a claim of provenance, not evidence of it.
- Cell range: Q3_Model.xlsx · Revenue!B14:F34enforced
105 cells. Open it, read the block, and a wrong citation is obvious immediately.
- Page: SPA.pdf, p.41
One page. Checkable, but still a paragraph hunt, and a page reference to a 40-row table narrows very little.
- Document: see the financial modelbypassable
The whole file. Checking costs the same as not having the answer, so in practice nobody checks and the citation does no work.
| Criterion | What the reader opens | Cells to scan | Detects a wrong citation |
|---|---|---|---|
| Document citation | The workbook | ~40,000 | No, in practice |
| Sheet citation | One sheet | ~3,300 | Rarely |
| Row-range citation | 21 rows, full width | ~500 | Sometimes |
| Cell-range citation | Revenue!B14:F34 | 105 | Yes, at a glance |
How the coordinate is produced
The range comes from the chunker, not from the model. Tables are chunked at 20 rows with a 5-row overlap, and each chunk records the sheet name, its row range and its column range, which are combined into A1 notation. The chunk text itself carries the locator, so the model is answering from a block that already knows its own address.
The hard part is that a chunk's array index is not its sheet row. A parsed table skips the header, and it excludes rows marked as totals so a subtotal does not shift everything below it. So the chunker keeps the original sheet row for every data row and maps slice boundaries back through it, then adds one, because sheet rows are 1-based everywhere a human sees them. The basis is a named constant, absolute-1based, and the worker reports it on its health endpoint so a machine still emitting the older table-relative numbering can be identified from outside rather than by reading its citations and noticing they point at the wrong cells.
The same problem appears again on the way back. The render model is sparse: hidden rows and rows that were never populated do not enter it, so row 14 is not the fourteenth row of the grid. The viewer keeps a map from absolute sheet row to grid row, and that map is the only legitimate translation. If a range's first row was hidden after indexing, the lookup searches forward for the start and backward for the end, so the band still lands on real content instead of failing.
- QuestionAsked in the room
- RetrieveChunks carry sheetName and cellRange
- AnswerMarkers attach to claims
- CitationRevenue!B14:F34
- WashSheet opens, cells flash amber for two seconds
Clicking a citation switches to the sheet, scrolls horizontally by summing the live zoom-scaled widths of the intervening columns while skipping hidden ones, leaves 24 pixels of context before the first cited column, then washes the range: the cited cells in amber, the rest of the cited row in a paler tint so five cells read as five cells and not as a full-width band. The wash clears after two seconds. The inspector strip opens on the range and names it back in absolute sheet coordinates, so the address on screen matches the address in the answer that sent the reader there.
Reproducing it
The coordinate contract has its own suite, including a case where excluded subtotal rows must not shift the cited range and a case where a multi-chunk table keeps every chunk anchored to real sheet rows:
npx playwright test -c tests/rag/spreadsheet/playwright.config.ts chunking # 31 passed (406ms), run 4 August 2026
Cell-range citations are only possible because the viewer renders a grid rather than a picture of one. That is the connection between this and the fidelity test: convert the workbook to PDF for viewing and the addresses are gone, so the best any citation can do afterwards is name a page.
Related: The spreadsheet fidelity test · Where a permission filter has to live · Arabic, Hijri and RTL in data rooms · Pricing
AI chat with page and cell-range citations is included in every paid tier. See pricing.