# HTML selection and provenance

This guide selects HTML, not the unrelated upstream PDF/Office corpus. No `renderers/results.json` exists: these are HTML-to-Markdown conversions, not GitHub.com or VS Code rendering tests.

- `corpus/article.html`: upstream full page with head title, cookie banner, navigation, article, SQL fence input, flat table and footer. Truth is upstream. The archived Markovo output corresponds to this exact input; source byte count matches the API snapshot. Created 2026-10-14, reused without another API call.
- `corpus/headerless.html`: locally constructed all-data table. No column labels exist. Empty Markdown headers preserve data roles; first-row inference promotes data into labels.
- `corpus/colgroup-header.html`: locally constructed table with `colgroup` before an explicit `th` row, without `thead`. This tests a sibling-position gate, not rowspan or colspan.
- `corpus/colgroup-thead.html`: controlled variant of the preceding input, wrapping only its header row in `thead`. Same visible contents and ground truth.

Each HTML has a truth JSON. Its `.txt` mirror has identical bytes and is the publishable input evidence. The `.html` itself is not declared in citations or lab_evidence. No PDF metrics are imported into the guide.

`run_html.py` executes installed MarkItDown, Markdownify (ATX heading style), Markdownify with article selection and code-language callback, Markdownify with header inference, and Pandoc's GFM writer on every selected input. The latter two Markdownify profiles are controls, not independent engines. MarkItDown's HTML path itself subclasses Markdownify: matching failures are not independent corroboration.

`upstream-runs.json` preserves the input manifest before local execution. `runs.json` merges local results with that archive. `scores.json` is generated unmodified by the repository `tools/lab_score.py`. Its full matrix includes upstream formats and tools that this guide does not discuss. The article uses only the selected HTML rows, and never treats archived zero elapsed values as timings.

The scorer checks same-line text containment, not semantic column alignment. For headerless inputs it emits 0 for absent truth headers; the guide marks that metric N/A, not a failed header. A header word match does not imply valid Markdown table syntax. The pipe-table flag exposes the colgroup failure. Code-block recall does not check a language label. Output inspection supplies that qualitative observation.

No packages were installed, no network calls were made by the experiment, and no external README instructions were executed. The example scripts were also run against a copy of the article input in `lab/examples/`; those copies are retained for reproducibility.
