llm-ingestion-okf/tests/test_corpus_run.py
Kjell Tore Guttormsen 4ce14ae5dd feat(cli): okf build, one installed command for folder in, bundle out
Until now "run the door over a folder" was a shell loop over two scripts
under `tools/`, with nine flags between them and a `--path-prefix` rule
that lived in a code block in a measurement report. Neither script was
packaged (`pyproject.toml` ships `src/llm_ingestion_okf` only), so the
path the published K1/K2 numbers were measured on was reachable from a
clone and nowhere else.

`okf build <folder> --bundle <dir>` is that path, packaged, declared as a
console script and installed with the wheel. It is orchestration only:
the proposer and the corpus harness MOVED into the package
(`llm_ingestion_okf.propose`, `llm_ingestion_okf.corpus`) and the two
`tools/` scripts became thin entry points to them, so the published
reproduction blocks still run and there is exactly one implementation of
each rule. Neither move adds a dependency or a model call.

Two decisions belong to this layer and are stated where they are made.
A document's proposed paths are scoped by its RELATIVE PATH minus the
extension, not its basename: the door walks recursively now, and two
documents named alike in different folders would otherwise collide on a
path Door B is supposed to make impossible rather than merely detect.
And omitted timestamps do not come from the clock -- `--ingested-at` and
`--proposed-at` default to one shared epoch constant, because a
wall-clock default would put a changing byte in the artifact and take
rebuild-equals-incremental away from every caller who did not pass them.

Arm C and Arm D stay off and are not exposed here.

Measured on the 43-file K2 corpus, one invocation against the two-script
bundle of 2026-09-03: N = 43 computed, merged 39/43, coded rejections
4/43 (`extractor_unknown` 3, `extractor_empty_pdf` 1), K1b 39 + 4 = 43,
exit 0, 779.43 s. 1107 of 1108 files byte-identical. The one that
differs is the root `index.md`, by exactly the `log.md` link a commit
fifteen hours younger than the stored artifact adds -- appending that
line to the stored file reproduces the new one byte for byte. Against
the two scripts at THIS commit the trees agree in full, which is what
the byte-identity test holds.

Suite 1127 passed after `git add` (1113 before), mypy --strict clean,
ruff clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 05:06:33 +02:00

507 lines
19 KiB
Python

"""The corpus harness: it reports numbers with denominators, or it fails.
Three properties, all of them reactions to measured defects rather than good
intentions:
- **K1b is a COMMAND, not a sentence in a report.** The conservation identity
`merged + Sigma(coded rejections) == N` is checked by the harness, which
EXITS NON-ZERO when it does not hold. A prose assertion is something a reader
has to trust; an exit status is something a pipeline cannot ignore.
- **`N` is computed, never typed.** A literal `43` keeps passing after the
corpus changes, and the number it then reports is a fact about a directory
that no longer exists.
- **Three counts, never one.** The guard sits between extraction and persist,
so a healthy persisted count can hide a pile of quarantines. Extracted,
gated and persisted are reported separately for that reason.
The negative control is the point of this module. A harness that can never
fail proves nothing, so `test_a_file_neither_merged_nor_coded_fails_the_run`
hands the conservation check an inventory it must reject -- if that test ever
passes silently, every green run above it becomes meaningless.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from llm_ingestion_okf import corpus as okf_corpus_run
INGESTED_AT = "2026-07-25T12:00:00Z"
SUBSTANTIVE = "Krav til seksjonering av bygget.\n\nEn andre setning som baerer innhold.\n"
DEGENERATE = " \n\t\n \n"
def corpus(tmp_path: Path, files: dict[str, str]) -> Path:
root = tmp_path / "corpus"
root.mkdir(parents=True, exist_ok=True)
for name, text in files.items():
(root / name).write_text(text, encoding="utf-8", newline="")
return root
def test_the_denominator_is_the_directory_not_a_literal(tmp_path: Path) -> None:
root = corpus(tmp_path, {"a.md": SUBSTANTIVE, "b.md": SUBSTANTIVE, "c.md": SUBSTANTIVE})
report = okf_corpus_run.measure(root, tmp_path / "bundle", ingested_at=INGESTED_AT)
assert report.n == 3
assert report.n == len(list(root.iterdir()))
def test_the_denominator_counts_files_in_subdirectories_too(tmp_path: Path) -> None:
"""N is the corpus, and the corpus is the whole tree.
The measurement and the door must walk by the SAME rule -- `walk_inbox` is
the one implementation -- or the report would state a denominator over a
different set of files than the one that was ingested, and the
conservation identity would hold over the wrong N.
"""
root = corpus(tmp_path, {"a.md": SUBSTANTIVE})
(root / "sub").mkdir()
(root / "sub" / "b.md").write_text(SUBSTANTIVE, encoding="utf-8", newline="")
report = okf_corpus_run.measure(root, tmp_path / "bundle", ingested_at=INGESTED_AT)
assert report.n == 2
assert report.persisted == 2
# `unaccounted` is `dropped - merged - coded`: it can only be empty if the
# measurement's names and the door's names are the SAME strings, which is
# what pins the two walks to one rule rather than to two that agree today.
assert report.unaccounted == ()
# Re-extracted through `corpus / source_file`, so the relative name has to
# resolve back to the file it came from.
assert report.substantive == 2
def test_the_denominator_skips_a_bundle_written_inside_the_corpus(tmp_path: Path) -> None:
root = corpus(tmp_path, {"a.md": SUBSTANTIVE})
bundle = root / "bundle"
okf_corpus_run.measure(root, bundle, ingested_at=INGESTED_AT)
second = okf_corpus_run.measure(root, bundle, ingested_at=INGESTED_AT)
assert second.n == 1
assert second.persisted == 1
assert second.unaccounted == ()
def test_the_conservation_identity_holds_and_the_run_exits_zero(tmp_path: Path) -> None:
root = corpus(
tmp_path,
{"a.md": SUBSTANTIVE, "b.md": DEGENERATE, "c.md": SUBSTANTIVE, "d.bin": "x"},
)
code = okf_corpus_run.main(
["--corpus", str(root), "--report", str(tmp_path / "r.md"), "--ingested-at", INGESTED_AT]
)
assert code == 0
report = okf_corpus_run.measure(root, tmp_path / "bundle2", ingested_at=INGESTED_AT)
assert report.merged + report.rejected == report.n
assert not report.unaccounted
def test_a_file_neither_merged_nor_coded_fails_the_run(tmp_path: Path) -> None:
"""The negative control. Without it a green run proves nothing.
The check is handed an inventory where one name is in neither column --
exactly what a silently dropped file looks like from the outside -- and it
must both refuse and NAME the file.
"""
unaccounted = okf_corpus_run.unaccounted_names(
dropped=("a.md", "b.md", "vanished.md"),
merged=("a.md",),
coded=("b.md",),
)
assert unaccounted == ("vanished.md",)
assert okf_corpus_run.unaccounted_names(dropped=("a.md",), merged=("a.md",), coded=()) == ()
def test_the_harness_exits_non_zero_and_names_the_unaccounted_file(
tmp_path: Path, capsys: pytest.CaptureFixture[str], monkeypatch: pytest.MonkeyPatch
) -> None:
root = corpus(tmp_path, {"a.md": SUBSTANTIVE, "b.md": SUBSTANTIVE})
real = okf_corpus_run.measure
def lose_one(*args: object, **kwargs: object):
report = real(*args, **kwargs) # type: ignore[arg-type]
return okf_corpus_run.replace(report, unaccounted=("b.md",))
monkeypatch.setattr(okf_corpus_run, "measure", lose_one)
code = okf_corpus_run.main(
["--corpus", str(root), "--report", str(tmp_path / "r.md"), "--ingested-at", INGESTED_AT]
)
assert code != 0
assert "b.md" in capsys.readouterr().err
def test_the_degenerate_rule_is_reproducible_from_its_statement(tmp_path: Path) -> None:
"""Zero characters after stripping whitespace. A definition, not a threshold."""
assert okf_corpus_run.is_degenerate("")
assert okf_corpus_run.is_degenerate(" \n\t ")
assert not okf_corpus_run.is_degenerate("x")
root = corpus(tmp_path, {"a.md": SUBSTANTIVE, "b.md": DEGENERATE})
report = okf_corpus_run.measure(root, tmp_path / "bundle", ingested_at=INGESTED_AT)
assert report.substantive == 1
assert report.degenerate == 1
assert report.substantive + report.degenerate == report.merged
def test_the_three_counts_are_reported_separately(tmp_path: Path) -> None:
"""A healthy persisted count can hide a pile of quarantines."""
root = corpus(tmp_path, {"a.md": SUBSTANTIVE, "b.bin": "x"})
report = okf_corpus_run.measure(root, tmp_path / "bundle", ingested_at=INGESTED_AT)
assert (report.extracted, report.gated, report.persisted) == (1, 1, 1)
assert report.n == 2
text = report.render()
for label in ("extracted", "gated", "persisted", "denominator"):
assert label in text
def test_the_report_names_the_resolved_converter_and_its_version(tmp_path: Path) -> None:
"""The vendored binary is bypassed silently otherwise -- measured three times."""
root = corpus(tmp_path, {"a.md": SUBSTANTIVE})
report = okf_corpus_run.measure(root, tmp_path / "bundle", ingested_at=INGESTED_AT)
text = report.render()
assert "converter" in text.lower()
assert okf_corpus_run.converter_identity()[1] in text
def test_wall_time_per_file_is_reported(tmp_path: Path) -> None:
"""The only evidence the scale requirement will ever have."""
root = corpus(tmp_path, {"a.md": SUBSTANTIVE, "b.md": SUBSTANTIVE})
report = okf_corpus_run.measure(root, tmp_path / "bundle", ingested_at=INGESTED_AT)
assert report.seconds_total >= 0.0
assert "per file" in report.render()
def test_the_bundle_carries_a_log_md_that_makes_k1b_checkable_from_the_bundle(
tmp_path: Path,
) -> None:
"""K1b was verifiable only from the harness's stdout, which no bundle carries.
Measured by a consumer 2026-09-03: given the bundle alone, `N` could not be
recovered, so `merged + Sigma(coded rejections) == N` was not checkable from
the artifact -- only `merged` was. SPEC section 9 already reserves `log.md`
for exactly this, so the run path writes the denominator and every rejection
code into it. Existence is not the property under test: an empty stub would
pass that and recover nothing.
"""
root = corpus(tmp_path, {"a.md": SUBSTANTIVE, "b.md": DEGENERATE, "c.bin": "x"})
bundle = tmp_path / "bundle"
code = okf_corpus_run.main(
[
"--corpus",
str(root),
"--report",
str(tmp_path / "r.md"),
"--bundle",
str(bundle),
"--ingested-at",
INGESTED_AT,
]
)
assert code == 0
log = (bundle / "log.md").read_text(encoding="utf-8")
# Section 9 form: reserved frontmatter type, a heading, ISO date headings.
assert log.startswith("---\ntype: Log\n")
assert f"\n## {INGESTED_AT[:10]}\n" in log
# The numbers, not merely the file. N is the denominator that was missing.
assert "N = 3" in log
assert "merged = 2" in log
assert "`extractor_unknown`: 1" in log
# The identity itself, so a reader does not have to re-derive it.
assert "2 + 1 = 3" in log
def test_the_log_is_dated_from_ingested_at_and_never_the_wall_clock(tmp_path: Path) -> None:
"""Determinism is bit-exact here as everywhere: two runs of the same corpus
at the same `ingested_at` produce the same `log.md` bytes."""
root = corpus(tmp_path, {"a.md": SUBSTANTIVE})
first = tmp_path / "b1"
second = tmp_path / "b2"
for bundle in (first, second):
okf_corpus_run.main(
[
"--corpus",
str(root),
"--report",
str(tmp_path / "r.md"),
"--bundle",
str(bundle),
"--ingested-at",
INGESTED_AT,
]
)
assert (first / "log.md").read_bytes() == (second / "log.md").read_bytes()
SEGMENTABLE = (
"# 1 Innledning\n\nBakgrunnen for anskaffelsen er beskrevet her, med nok\n"
"tekst til at seksjonen baerer innhold.\n\n"
"# 2 Kravspesifikasjon\n\nKravene til leveransen er listet i dette\n"
"avsnittet, ogsaa med en andre setning.\n"
)
def _propose(source: Path, out: Path) -> None:
from llm_ingestion_okf import propose
assert propose.run(source, out, okf_type="reference", proposed_at=INGESTED_AT) == 0
def test_a_plan_directory_makes_the_run_segment_and_mark_every_concept_proposed(
tmp_path: Path,
) -> None:
"""The defect this closes: the harness ran under `STRUCTURED_V1` and passed
no plans at all, so a corpus arrived as one flat concept per file with no
`adjudication` key anywhere -- measured by a consumer as 0 of 39.
Segmentation is not a flag the harness may set on its own: the plans are
produced per document by the proposer first, and the harness replays them.
So the wiring under test is `--plans-dir`, and the profile follows from it.
"""
root = corpus(tmp_path, {"doc.md": SEGMENTABLE})
plans = tmp_path / "plans"
plans.mkdir()
_propose(root / "doc.md", plans / "doc.json")
bundle = tmp_path / "bundle"
code = okf_corpus_run.main(
[
"--corpus",
str(root),
"--report",
str(tmp_path / "r.md"),
"--bundle",
str(bundle),
"--ingested-at",
INGESTED_AT,
"--plans-dir",
str(plans),
"--bundle-id",
"k2-trinn1",
"--okf-version",
"0.2",
]
)
assert code == 0
concepts = sorted(
path for path in bundle.rglob("*.md") if path.name not in ("index.md", "log.md")
)
# 1-to-N: one dropped file, more than one concept.
assert len(concepts) > 1
bodies = [path.read_text(encoding="utf-8") for path in concepts]
# Every concept carries the marker, and it says PROPOSED -- the proposer
# never adjudicates, so an `adjudicated` here would be a machine's guess
# standing where a human's judgement belongs.
assert all("\nadjudication: proposed\n" in body for body in bodies)
assert not any("adjudication: adjudicated" in body for body in bodies)
def test_a_plan_directory_without_the_caller_owned_root_values_is_refused(
tmp_path: Path,
) -> None:
"""`okf_version`'s value belongs to the catalog (decision E1) and `bundle_id`
to whoever delimits the bundle. A literal for either in this harness would
claim a decision this repository does not own, so both are arguments and
their absence is a refusal rather than a default."""
root = corpus(tmp_path, {"doc.md": SEGMENTABLE})
plans = tmp_path / "plans"
plans.mkdir()
_propose(root / "doc.md", plans / "doc.json")
code = okf_corpus_run.main(
[
"--corpus",
str(root),
"--report",
str(tmp_path / "r.md"),
"--bundle",
str(tmp_path / "bundle"),
"--ingested-at",
INGESTED_AT,
"--plans-dir",
str(plans),
]
)
assert code == 2
assert not (tmp_path / "bundle").exists()
def test_without_a_plan_directory_the_run_is_unchanged(tmp_path: Path) -> None:
"""The wiring is additive. A run with no plans stays exactly the flat,
`STRUCTURED_V1` run it was, so the K1/K2 numbers already published remain
reproducible from the same command."""
root = corpus(tmp_path, {"doc.md": SEGMENTABLE})
bundle = tmp_path / "bundle"
assert (
okf_corpus_run.main(
[
"--corpus",
str(root),
"--report",
str(tmp_path / "r.md"),
"--bundle",
str(bundle),
"--ingested-at",
INGESTED_AT,
]
)
== 0
)
concepts = [path for path in bundle.rglob("*.md") if path.name not in ("index.md", "log.md")]
assert len(concepts) == 1
assert "adjudication:" not in concepts[0].read_text(encoding="utf-8")
def test_a_second_run_into_the_same_bundle_reproduces_it_byte_for_byte(tmp_path: Path) -> None:
"""`log.md` is a file the harness writes INTO a directory Door B enumerates
on the next round: it matches the concept glob and is excluded only by
`index.md`'s name, so a rebuild could see it as pre-existing curated content
or prune it. Rebuild-equals-incremental is the property the segmented bundle
is built on, and a log that broke it would be worse than no log.
"""
root = corpus(tmp_path, {"doc.md": SEGMENTABLE, "flat.md": SUBSTANTIVE})
plans = tmp_path / "plans"
plans.mkdir()
_propose(root / "doc.md", plans / "doc.json")
bundle = tmp_path / "bundle"
argv = [
"--corpus",
str(root),
"--report",
str(tmp_path / "r.md"),
"--bundle",
str(bundle),
"--ingested-at",
INGESTED_AT,
"--plans-dir",
str(plans),
"--bundle-id",
"k2",
"--okf-version",
"0.2",
]
assert okf_corpus_run.main(argv) == 0
first = {
path.relative_to(bundle).as_posix(): path.read_bytes()
for path in sorted(bundle.rglob("*"))
if path.is_file()
}
assert "log.md" in first
assert okf_corpus_run.main(argv) == 0
second = {
path.relative_to(bundle).as_posix(): path.read_bytes()
for path in sorted(bundle.rglob("*"))
if path.is_file()
}
assert second == first
def test_the_root_index_links_the_bundles_own_log(tmp_path: Path) -> None:
"""A log nothing links is a file on disk, not a member of the bundle.
Measured on the artifact: the K2 bundle carried a conformant root `log.md`
that no index named, so a consumer walking the bundle from `index.md` --
which is the walk section 8 exists to support -- never reached the one file
carrying `N`.
This is a LOCAL choice, not a conformance requirement, and the distinction
is worth keeping straight. Section 9 lets `log.md` sit at any level and
section 8 has an index enumerate its directory's contents, but upstream's
own reference bundles do not link it: measured at `9a15b13`, 0 of the 24
shipped `index.md` files name the single `log.md` in the bundle set. So
upstream proves the link is not required, not that it is disallowed.
It is made HERE, in the harness, because the library cannot make it. The
log's content is the run's outcome, so it cannot be written before the
indexes are projected -- and an index that enumerated `log.md` off the
directory would gain the link only on the SECOND run, breaking the
rebuild-equals-incremental property the segmented bundle is built on. The
harness instead writes the link after the log, and only when it is not
already there -- a test, not an append, because the two reprojections
disagree about this line: the per-directory one drops it as a managed
entry, the flat one keeps it because its target is not an owned concept.
"""
root = corpus(tmp_path, {"doc.md": SEGMENTABLE, "flat.md": SUBSTANTIVE})
plans = tmp_path / "plans"
plans.mkdir()
_propose(root / "doc.md", plans / "doc.json")
bundle = tmp_path / "bundle"
argv = [
"--corpus",
str(root),
"--report",
str(tmp_path / "r.md"),
"--bundle",
str(bundle),
"--ingested-at",
INGESTED_AT,
"--plans-dir",
str(plans),
"--bundle-id",
"k2",
"--okf-version",
"0.2",
]
assert okf_corpus_run.main(argv) == 0
index = (bundle / "index.md").read_text(encoding="utf-8")
assert "](log.md)" in index
assert index.count("](log.md)") == 1
# The link is to the log in THIS directory, so a nested index must not
# carry one: there is no `log.md` beside it to reach.
for nested in bundle.rglob("*/index.md"):
assert "](log.md)" not in nested.read_text(encoding="utf-8")
# Rebuild equals incremental, still. This is what discriminates the two
# ways the append could be wrong: a link the reprojection keeps would be
# doubled here, and one the harness forgot to re-write would vanish.
first = {
path.relative_to(bundle).as_posix(): path.read_bytes()
for path in sorted(bundle.rglob("*"))
if path.is_file()
}
assert okf_corpus_run.main(argv) == 0
second = {
path.relative_to(bundle).as_posix(): path.read_bytes()
for path in sorted(bundle.rglob("*"))
if path.is_file()
}
assert second == first
def test_the_log_link_holds_on_the_unsegmented_path_too(tmp_path: Path) -> None:
"""The two run modes reproject through different code, so both are pinned.
A run without `--plans-dir` uses `STRUCTURED_V1`, whose index is not
per-directory and is rewritten by the singular reprojection rather than the
per-directory one. The harness writes `log.md` in both modes, so a link
that only held on the segmented path would leave the plainer bundle with
exactly the orphan this closes -- and if that path kept the line instead of
dropping it, the second run would carry two.
"""
root = corpus(tmp_path, {"a.md": SUBSTANTIVE, "b.md": SUBSTANTIVE})
bundle = tmp_path / "bundle"
argv = [
"--corpus",
str(root),
"--report",
str(tmp_path / "r.md"),
"--bundle",
str(bundle),
"--ingested-at",
INGESTED_AT,
]
assert okf_corpus_run.main(argv) == 0
index = (bundle / "index.md").read_text(encoding="utf-8")
assert "](log.md)" in index
assert okf_corpus_run.main(argv) == 0
assert (bundle / "index.md").read_text(encoding="utf-8") == index