Two producer-side findings from the consumer's S7c acid test (ordre 20260908T063454Z-3648220855-from-.claude), both measured on K2 before and after, both with the corpus rebuilt from scratch.
FUNN 3 -- THE FORM. The converter's default markdown writer emits simple tables, which pad every cell out to the width of the widest cell in its column. Measured on the tender's price sheet: one 594-character prose cell produced a 67 244-character whitespace carpet with runs of up to 887 characters between a label and its amount, 19 integral amounts carrying a converter `.0`, and a header row naming one column. The bytes reached a live model in 2 of 11 prompts and 0 of 11 answers. The spreadsheet row now writes pipe tables with `--columns=1` (load-bearing: the pipe writer pads to a width computed from it, so at the default 72 a narrow table gains runs of up to 45). Same sheet after: 11 048 characters, longest run 2, one row per line, 0 artificial `.0`. Spreadsheet-only, and the scoping is pinned by three digests -- the same change moves the odt fixture 1366 -> 1105, so it can fail.
The `.0` rewrite is bounded twice: to a cell whose whole content is such a number, anchored between unescaped pipes, and skipped when the literal is in the workbook's shared string table -- the converter renders the number 92 and the TEXT "92.0" identically, so the output alone cannot tell them apart. Read with zipfile and xml.etree; no new dependency.
FUNN 2 -- THE LOG LINK. `link_log_in_root_index` (95eb271) is removed. Consumption contract SS 9.2 forbids a consumer from enumerating the bundle directory unless the profile says the index is derived, so the index tree is the entire map a consumer may use and everything it links is a document: their navigator returned 630 where our pre-pass counts 629, and a corpus run's own log was citable as content. The log is still written to the bundle root (SPEC section 9); `tools/okf_consume.py` keeps its exclusion for the bundles already built with the link.
K2 rebuilt twice. BEFORE reproduces the consumer's ref exactly (`sha256-tree:f14872a0...c8a92a`, 629 concepts) and their three consume figures to the token (57 289 / 62 149 / 58 401). AFTER: 629 concepts, `merged + coded rejections = 43 = N`, new ref `sha256-tree:c26eed6a...e3261f`, 627 of 629 concepts byte-identical, 1104 of 1108 files identical to the delivered bundle.
ONE REGRESSION, MEASURED AND NOT FIXED: on the mandate-shaped question with the vocabulary bridge the priced concept moves from candidate rank 10 to 19, so `--k 12` withholds it `below_k`; `--cost-vocabulary --k 20` delivers it at 65 912 o200k. The cause is measured rather than argued -- restoring only the concept's title on the new short body ranks it 10 again. The chain ends at the orphan check (`propose.py:461`), which drops the sheet heading once a table block opens two lines below it. That is the already-reported orphan gate, and changing it is a default-ON segmentation rule affecting every document type. The specific question is unaffected: rank 1 before and after. The priced excerpt's budget share falls from 56.5 % to 9.7 %.
11 new tests (RED first), 8 mutations, 8 red, with an unmutated control green each time. One mutation survived twice before the fixture could make it fire, and both survivals are written down. 1279 -> 1287 tests. mypy --strict clean on 28 files. ruff clean. Both proposer goldens byte-unchanged. One frozen literal moved with the fix and is reported rather than hidden.
Report: docs/2026-09-08-prisform-og-loggen-k2.md
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
496 lines
19 KiB
Python
496 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_does_not_link_the_bundles_own_log(tmp_path: Path) -> None:
|
|
"""The log is in the bundle and out of the index. Both halves matter.
|
|
|
|
The harness DID link it (`95eb271`), so a consumer entering at `index.md`
|
|
could reach the one file carrying `N`. That was a LOCAL choice and said so:
|
|
upstream's own reference bundles do not link their logs -- measured at
|
|
`9a15b13`, 0 of the 24 shipped `index.md` files name the single `log.md` in
|
|
the bundle set -- so upstream showed the link was permitted, never required.
|
|
|
|
It was removed on 2026-09-08 because the cost was measured. Consumption
|
|
contract SS 9.2 forbids a consumer from enumerating the bundle directory
|
|
unless the named profile says the index is derived, so the index tree is the
|
|
ENTIRE map a consumer may use and everything it links is a document. A
|
|
consumer walking K2 that way returned 630 documents where our own pre-pass
|
|
counts 629, and the corpus run's own log was readable and citable as
|
|
content. `5a0c879` fixed the count on our side of a disagreement produced on
|
|
this one.
|
|
|
|
Section 9 still puts `log.md` at any level, and it is still written there.
|
|
"""
|
|
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
|
|
assert (bundle / "log.md").is_file(), "the log is still written to the bundle"
|
|
for index_path in bundle.rglob("index.md"):
|
|
assert "log.md" not in index_path.read_text(encoding="utf-8"), index_path
|
|
|
|
# Rebuild equals incremental, still -- the property the removed append was
|
|
# most likely to break, and the one that has to survive its removal too.
|
|
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_unsegmented_path_leaves_the_log_out_of_the_index_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 removed append behaved differently under the two --
|
|
the per-directory reprojection dropped the line, the flat one kept it -- so
|
|
a removal verified on one path only would prove nothing about the other.
|
|
"""
|
|
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
|
|
assert (bundle / "log.md").is_file()
|
|
index = (bundle / "index.md").read_text(encoding="utf-8")
|
|
assert "log.md" not in index
|
|
|
|
assert okf_corpus_run.main(argv) == 0
|
|
assert (bundle / "index.md").read_text(encoding="utf-8") == index
|