llm-ingestion-okf/tests/test_table_measure.py
Kjell Tore Guttormsen 36c201cc8a chore(ruff): the acceptance was whatever the default happened to be [skip-docs]
`uv sync --frozen` resolved ruff 0.15.22 and the tree read clean. A loose
install resolves 0.16.6, under which the SAME untouched code reports 148
findings -- 4 more than round 9 counted, because this round added four files.
All of them are new rules rather than new defects: 0.16 widened the default
rule set to whole families (YTT, ASYNC, PL, ISC, C4, UP, B, SIM, FURB, ...).

(`[skip-docs]` is for CLAUDE.md, which a lint-configuration change does not
reach. README's developer section IS updated in this commit.)

THE DEFECT IS NOT THE 148, IT IS THAT NOBODY CHOSE THEM. `[tool.ruff]` set only
`line-length` and `target-version`, so the acceptance was ruff's default, and
the tree stayed green only as long as the lockfile froze an old ruff. `select`
is now written down: `E4`, `E7`, `E9`, `F` (the historical default), `I`
because this tree already keeps imports sorted, and `RUF100` so a `noqa` that
has stopped meaning anything is caught rather than left as decoration. Pin
`ruff>=0.9` -> `ruff>=0.16.6,<0.17`.

Per rule, before -> after: RUF100 50 -> 0, I001 20 -> 0, ISC004 19, PLW1510 8,
C408 8, EXE001 6, RUF007 5, PLE2515 4, UP031 3, B017 3, and fourteen more with
2 or fewer -- the families out of the declared set are 0 by selection, and 148
is the number to start from if they are adopted, which is a separate decision
and not one to take inside a version-pin commit. 57 were auto-fixed; one E402
was reintroduced by the import-sorting fix merging a block away from its
`noqa`, and got the directive back rather than a bare one.

`S` IS MEASURED OUT, NOT ASSUMED OUT: it reports 2657 `S101` on a suite whose
every assertion is an `assert`, and `S603` flags 19 subprocess calls of which
one was ever marked -- selecting it buys 18 suppressions and no defect. Two
`noqa` directives naming non-selected rules were dropped with that reason
recorded in the configuration instead.

THE TWO FILES 0.16 WOULD REFORMAT ARE MARKDOWN, NOT PYTHON: `README.md` and
`docs/2026-09-08-blindsone-below-k-k2.md`. 0.16 formats fenced Python inside
markdown, and both blocks are RECORDS -- the second is a quotation of
`COST_VOCABULARY` as it stood when that measurement was taken. Reformatting a
quotation makes it stop being one, so markdown is excluded from the formatter
and `ruff format --check .` stays in the acceptance over `.py`.

`tools/okf_consume_measure.py` is fenced by the order as run-not-edited, so its
three findings are exempted by path with the reason and the debt named, and its
bytes are untouched.

THE LOCKFILE TRAP IS CLOSED, NOT AVOIDED. `uv.lock` predated the `[ocr]` extra,
so any unlocked resolve wrote that extra's transitive tree back into it -- 681
insertions over 4 deletions, twice now, and round 9 recorded the cause as
`uv run` OUTSIDE the project when it is `uv run` without `--frozen` INSIDE it.
The relock is complete for every declared extra (703 insertions, 26 deletions),
and measured after it, an unfrozen `uv run` leaves the file alone.

`ruff check src tests tools`, `ruff format --check .` (0.16.6), `mypy src` over
21 files and 1535 tests, all green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 23:15:17 +02:00

134 lines
5.3 KiB
Python

"""The grid-table reach instrument: order 20260907T075834Z-18584396-from-.claude.
Measures how far Arm E's grid-rule join reaches into a corpus, and -- the part
the round actually needs -- how many documents carry a `|` table row at all.
That count is the CEILING: Arm E cannot move a document that has no table row,
so a ceiling asserted from entry counts alone would rest on the orphan check
having kept every table candidate, which nobody measured.
The identity test below is the one that matters most, for the reason
`test_outline_measure.py` gives: an instrument that re-implements the grammar it
measures is measuring a SECOND definition, free to drift from the shipped one
without a test going red. `is`, not `==` -- `re.compile` returns a distinct
object for an equal pattern, so equality would be satisfied by a copied literal
and identity is what catches it.
The negative control is zero WITH a nonzero denominator. A document holding a
markdown pipe table has table rows and no grid rules, so it must report
`grid_rule_lines == 0` while `pipe_rows` is positive: "found nothing" and
"measured nothing" are different results and only one of them is evidence.
"""
from __future__ import annotations
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "tools"))
import okf_outline_measure
import okf_table_measure
from llm_ingestion_okf import propose as okf_propose_segments
GRID_DOC = """+-------+-------+
| Navn | Verdi |
+=======+=======+
| Areal | 120 |
+-------+-------+
| Hoyde | 3 |
+-------+-------+
"""
PIPE_DOC = """| Navn | Verdi |
|-------|-------|
| Areal | 120 |
Etterfoelgende avsnitt.
"""
NO_TABLE_DOC = """# Teknisk grunnlag
Innledende tekst uten tabell i det hele tatt.
"""
def test_the_instrument_and_the_tool_are_one_definition() -> None:
"""Identity, not equality: the cheapest proof there is no second grammar.
The regex identities are the load-bearing ones. `re.compile(p) == re.compile(p)`
is False in CPython, so `==` would be the wrong operator anyway -- but a
module that pasted the pattern literal would still LOOK right, and only
`is` says it came from the shipped module.
"""
assert okf_table_measure.find_candidates is okf_propose_segments.find_candidates
assert okf_table_measure._GRID_RULE is okf_propose_segments._GRID_RULE
assert okf_table_measure._TABLE_ROW is okf_propose_segments._TABLE_ROW
assert okf_table_measure.RULE_TABLE_GRID is okf_propose_segments.RULE_TABLE_GRID
assert okf_table_measure.RULE_TABLE_BLOCK is okf_propose_segments.RULE_TABLE_BLOCK
def test_the_draw_is_the_committed_one() -> None:
"""One K3 draw in the repository, not two that can disagree."""
assert okf_table_measure.draw_sample is okf_outline_measure.draw_sample
def test_a_hand_computed_grid_table_reports_its_figures() -> None:
"""Every field computed by hand from the fixture, not by calling the code.
The document is three row groups separated by rule lines: 3 `|` rows, 4
rule lines (top, header separator, and two more), 3 blocks today, 1 after
the join, 1 block joined, 3 entries before and 1 after.
"""
measurement = okf_table_measure.measure_document(GRID_DOC, "grid.md")
assert measurement.pipe_rows == 3
assert measurement.grid_rule_lines == 4
assert measurement.blocks_before == 3
assert measurement.blocks_after == 1
assert measurement.joined_blocks == 1
assert measurement.entries_before == 3
assert measurement.entries_after == 1
def test_a_document_with_pipe_tables_and_no_grid_rules_reports_zero_with_a_nonzero_denominator() -> (
None
):
"""Zero reach is evidence only when something was measured."""
measurement = okf_table_measure.measure_document(PIPE_DOC, "pipe.md")
assert measurement.grid_rule_lines == 0
assert measurement.joined_blocks == 0
assert measurement.blocks_before == measurement.blocks_after == 1
assert measurement.pipe_rows > 0
assert measurement.entries_before == measurement.entries_after
def test_a_document_with_no_table_at_all_is_zero_across_the_board() -> None:
"""The other denominator: a document Arm E cannot reach, and cannot claim."""
measurement = okf_table_measure.measure_document(NO_TABLE_DOC, "prose.md")
assert measurement.pipe_rows == 0
assert measurement.grid_rule_lines == 0
assert measurement.blocks_before == 0
assert measurement.entries_before == measurement.entries_after == 1
def test_an_empty_document_does_not_crash() -> None:
measurement = okf_table_measure.measure_document("", "empty.md")
assert measurement.pipe_rows == 0
assert measurement.entries_before == 0
def test_a_non_extractable_file_becomes_a_row_with_a_skip_reason(tmp_path: Path) -> None:
"""A file the door refuses stays in the denominator with its reason named.
Dropping it would make `extractable / len(rows)` unmeasurable, and that
ratio is the door count this round reports as 39/43.
"""
(tmp_path / "a.md").write_text(GRID_DOC, encoding="utf-8", newline="")
(tmp_path / "b.xyz").write_bytes(b"not a known type")
rows = okf_table_measure.run(tmp_path)
assert len(rows) == 2
measured = [r for r in rows if r.measurement is not None]
skipped = [r for r in rows if r.measurement is None]
assert len(measured) == 1
assert len(skipped) == 1
assert skipped[0].skip_reason