docs(k3): round 13, and the two proposer rules between a reader and its ceiling [skip-docs]

The reader reaches the ceiling and the build does not, and the report separates
the two with denominators and a control for each: the orphan check removes 710
of 2 761 (710 of 710 removed headings are followed immediately by another
heading; 0 of 2 051 delivered ones are), and Arm F removes 2 066 more, swept
one flag at a time.

Both instrument forms on every row, because the pair key scores 28 of 2 761
here for a reason that has nothing to do with segmentation -- and the shipped
instrument turns out to carry the round-12 correction in NO block, not just in
the three the order named. That is proposed to the owning repository, never
applied there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-10 04:13:56 +02:00
commit 9d5ebc3c29
2 changed files with 327 additions and 0 deletions

View file

@ -9,6 +9,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- **`.xml` is a core file type, NISO-STS aware, with a generic fallback.** A
publisher's own viewer delivers a zip that holds 0 html, 1 xml and 109
images; `okf build` on it was **110 of 110 unreadable, 0 plans, exit 2**, and
the conservation identity `merged + coded rejections == N` was never written
because the run aborted earlier. The one xml file is the whole product: 7 715
`<sec>`, **2 761 with a `<title>`**, 4 954 lettered points, 10
`<table-wrap>`, and a `<sec>`-nesting depth distribution row-for-row
identical to the publisher's own structure fasit.
- The output grammar is MARKDOWN, the same the office and HTML rows reach the
proposer through: `propose.py` is untouched. `<label>` + `<title>` become
one ATX line at the section's own depth; a `<sec>` with only a `<label>` is
a body line and never a heading (**0 of 4 954** became concepts);
`<table-wrap>` becomes one markdown table (**10 of 10**, against 0 of 10 on
the PDF path).
- The reader emits **2 761 of 2 761** heading lines and preserves text
exactly -- 1 283 395 of 1 283 395 non-whitespace characters, ratio
**1.000000**. The BUILD reaches 2 065 of 2 761 with `--no-unit-fold` and 15
of 2 761 on the shipped defaults; the whole distance is two proposer rules,
decomposed with denominators in the report.
- hit@k over six questions, k=50: **3/6 · 5/6 · 6/6**, matching the PDF arm
row for row, with the known-positive moving from **rank 13 to rank 1**.
2 022 concept ids are shared between the two channels -- 96.8 % of the XML
bundle.
- **No new dependency:** `xml.etree.ElementTree` is stdlib and `uv.lock` is
untouched. A `<!DOCTYPE` is REFUSED unparsed with its own code, which is a
guarantee about this package rather than about the installed libexpat.
- `.xml` never routes through the converter, and it is measured about 12x
faster and about 30x smaller in peak memory than the PDF arm on the same
document and the same machine.
- Report: `docs/2026-09-11-k3-runde13-xml-sts.md`.
### Fixed
- **A PDF bookmark sharing a line with another left no trace.** `pdf_outline`
collected marks in a dict keyed on the destination line index, so a second
bookmark on a line was discarded by `setdefault` in silence: measured on a
701-page document, **2 763 nodes in, 2 762 marks out, `unresolved` = 0**.
`PdfOutline` now carries `collided`, and the identity `nodes in == marks +
unresolved + collided` holds. Keeping both nodes was measured and felled --
the two candidates then open at one offset and the first closes with an empty
span the orphan check deletes.
- **`--pdf-outline` (OFF): cut a PDF at the boundaries its own `/Outlines`
bookmark tree declares.** Measured outside this repository on one 701-page
process code whose publisher also ships a NISO-STS structure for it: the