Get a free API key

This page as Markdown, byte for byte: /ingest-honesty.md

What Ingest survives, flags and refuses#

The honesty exhibit: what Ingest reads, what it admits it guessed at, and what it will not read at all — measured on the golden corpus rather than described. Every number below is computed from the corpus manifests and the pinned oracle outputs by tests/unit/test_honesty_exhibit.py, which re-renders this page and fails the build if a single figure has moved. Nothing here is typed by hand, and nothing here is a target: it is a measurement of what this build does with the ugliest files we could find.

The files this is measured on#

The corpus is corpus/, declared in corpus/manifest.d/*.yaml: 16 real-world-cursed files, append-only by specification — files and their expected outputs are added, never weakened or removed. It carries 138 declared rows across the 11 entries that state a row count; 5 state none. The manifests name 49 curse tags on 11 entries (none of them repeated), and 5 further entries describe their curses in a prose note instead.

Format Files
csv 8
(not declared) 5
fixed-width 1
jsonl 1
pdftotext-layout 1
Source encoding Files
utf-8 10
cp1252 2
ascii 1
iso-8859-15 1
utf-16 1
utf-8-sig 1

What it survives#

13 of the 16 files ingest to canonical risk objects — 64 objects in all — and those objects are pinned byte for byte under corpus/expected/. The oracle runs on every merge and 100% is the only passing grade, so this table is what the build enforces, not what it hopes for. It lists the whole corpus, refused files included, with the outcome the oracle pins for each.

File Format Encoding Rows Curses Outcome
Harburn_Group_SOV_2026_FINAL_v3 (2).csv csv utf-8 14 4 read
Pennard & Vale Estates - Loc Schedule FY26 (broker copy).csv csv iso-8859-15 12 4 read
Copy of Meridian RE SOV v2 FINAL FINAL.csv csv utf-8 16 4 read
SOV_combined FINAL (use this one) v7.xlsx.csv csv utf-8 16 5 read
Ashworth Portfolio – Occupancy Schedule 2026 (FINAL).csv csv cp1252 13 4 read
Prem Bdx Q2 2026 FINAL (2).csv (not declared) utf-8 1 (prose) read
Renewals 2026 v3 - Copy.csv (not declared) utf-8 1 (prose) read
boderaux_export_EU_v3.csv (not declared) cp1252 1 (prose) read
PREMWRITTEN_FY2025_legacy_extract.txt (not declared) utf-16 1 (prose) refused
program_summary_2026_clean.csv (not declared) utf-8 1 (prose) read
Drought+Weather Station Trigger Sched 2026 (AB edits) v4.csv csv utf-8 12 4 read
outage exposure list - cloud+grid MERGED final2.csv csv utf-8 10 4 read
EQPORT26_MAINFRAME.PRN fixed-width ascii 14 5 refused
eq_locs dump 2026-07-14T0312 prod.jsonl jsonl utf-8 9 4 read
NamedStorm_CatCircle_Schedule_FY26.pdf.txt pdftotext-layout utf-8 9 6 refused
flood_wildfire footprint expo (merged) - Sheet1.csv csv utf-8-sig 13 5 read

The curses each file declares, by name — the manifests' own words, which is why they read as a bug list rather than a brochure:

The remaining 5 entries state their curses as prose in the manifest rather than as tags; they are counted above but not listed here, because a sentence and a tag are not the same unit.

Not printed above: 1 of the tags counted earlier, on 1 of the files. They name a punctuation character whose own name is one of the words the perimeter scan will not let a product page carry (SPEC §4, P2). The manifests hold them in full, and this sentence is here so the arithmetic still reconciles.

What it flags into source_fidelity#

What Ingest could not confidently normalise goes on the object it produced, in exposure.source_fidelity. The published schema makes all 3 of its lists mandatory — unmapped_columns, guessed_units, ambiguous_rows — so "nothing was guessed" has to be stated as an empty list rather than inferred from a missing key. Nothing is silently dropped, and nothing is silently repaired.

Across the 13 files it reads, this build records 103 distinct honesty entries; every one of those files carries at least one. Entries are counted once per file: a file that ingests to several objects repeats its file-level notes on each of them, and counting the repetitions would flatter the exhibit.

File Objects unmapped_columns guessed_units ambiguous_rows
Harburn_Group_SOV_2026_FINAL_v3 (2).csv 1 0 3 0
Pennard & Vale Estates - Loc Schedule FY26 (broker copy).csv 1 1 2 1
Copy of Meridian RE SOV v2 FINAL FINAL.csv 1 1 1 0
SOV_combined FINAL (use this one) v7.xlsx.csv 1 1 1 12
Ashworth Portfolio – Occupancy Schedule 2026 (FINAL).csv 1 2 2 1
Prem Bdx Q2 2026 FINAL (2).csv 12 6 0 5
Renewals 2026 v3 - Copy.csv 12 4 3 4
boderaux_export_EU_v3.csv 10 2 4 1
program_summary_2026_clean.csv 10 4 0 5
Drought+Weather Station Trigger Sched 2026 (AB edits) v4.csv 1 5 0 0
outage exposure list - cloud+grid MERGED final2.csv 10 4 10 6
eq_locs dump 2026-07-14T0312 prod.jsonl 1 3 2 1
flood_wildfire footprint expo (merged) - Sheet1.csv 3 1 1 4
All 13 64 34 29 40

What it refuses#

3 of the 16 files are refused outright, and the refusal is pinned in the same oracle as every accepted output: a .rejected.json beside the expected outputs, carrying the verdict and the reason. A refusal is an answer, not a gap — it is what stops a later version quietly starting to guess.

Refusal also happens below the file: a record Ingest cannot parse is reported, never dropped and never repaired into a total. The corpus pins that case too — one JSON Lines file carries a malformed record, and its expected output carries the object built from the rest of the file with the bad record declared in ambiguous_rows.

What Ingest never does is decide whether a risk is worth taking. It classifies data; a file it reads is not a risk it has accepted, and a file it refuses is not a risk it has declined (SPEC §3.1).

Where each number comes from#