feat(inbox): root frontmatter emission at Door B with a caller-owned bundle_id

This commit is contained in:
Kjell Tore Guttormsen 2026-09-01 00:04:09 +02:00
commit 224121f762
2 changed files with 214 additions and 2 deletions

View file

@ -0,0 +1,172 @@
"""Bundle identity at Door B: the caller names the bundle, the door mirrors it.
Order `2527032751` settled the form: **(c) a root-frontmatter bundle
identifier that consumers join on**. Two facts made this new wiring rather than
a value change. First, `root_frontmatter` had ZERO references in `inbox.py`:
Door B seeded its index with an empty file and no frontmatter block at all,
where Door A has carried the machinery since D5. Second, identity had to be
CALLER-owned a bundle is a collection the caller delimits, so hashing its
contents would hand it a new identity every time a document was added.
That is also why there are two identity mechanisms in this library, stated
rather than hidden: WITHIN a bundle, Door C keys on a content hash; ACROSS
bundles, identity is this caller-assigned `bundle_id`. A consumer meets both.
S4b is resolved as ONE branch, not two: the root index is the SOURCE (the
caller supplies the value exactly once, D5 intact) and each concept MIRRORS
it. Two bundles built from identical inputs therefore hold concepts whose
paths COLLIDE by construction and whose identity values are disjoint the
collision is the expected behaviour under form (c), not a defect.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from llm_ingestion_okf.errors import MaterializationError
from llm_ingestion_okf.inbox import GateDecision, process_inbox
from llm_ingestion_okf.profiles import DEFAULT, SEGMENTED_V1, STRUCTURED_V1
INGESTED_AT = "2026-07-25T12:00:00Z"
DOCUMENT = "# Brannkonsept\n\nSeksjonering etter N500.\n"
def gate(text: str) -> GateDecision:
return GateDecision(sanitized_text=text, disposition="warn")
def drop(inbox: Path, name: str, text: str = DOCUMENT) -> None:
inbox.mkdir(parents=True, exist_ok=True)
(inbox / name).write_text(text, encoding="utf-8", newline="")
def run(tmp: Path, *, profile=SEGMENTED_V1, values=None, round_name: str = "round"):
return process_inbox(
tmp / round_name,
tmp / "bundle",
INGESTED_AT,
okf_type="reference",
gate=gate,
profile=profile,
root_frontmatter_values=values,
)
def tree(bundle: Path) -> dict[str, bytes]:
"""Every file under the bundle, keyed by bundle-relative path."""
if not bundle.is_dir():
return {}
return {
str(path.relative_to(bundle)): path.read_bytes()
for path in sorted(bundle.rglob("*"))
if path.is_file()
}
# --- additivity: the four shipped profiles do not move --------------------
def test_default_without_values_writes_what_it_wrote_before(tmp_path: Path) -> None:
drop(tmp_path / "a", "n500-vegbygging.md")
process_inbox(
tmp_path / "a",
tmp_path / "old",
INGESTED_AT,
okf_type="reference",
gate=gate,
profile=DEFAULT,
)
drop(tmp_path / "b", "n500-vegbygging.md")
process_inbox(
tmp_path / "b",
tmp_path / "new",
INGESTED_AT,
okf_type="reference",
gate=gate,
profile=DEFAULT,
root_frontmatter_values=None,
)
assert tree(tmp_path / "new") == tree(tmp_path / "old")
assert not (tmp_path / "new" / "index.md").read_text(encoding="utf-8").startswith("---")
def test_structured_v1_without_values_still_writes_no_frontmatter(tmp_path: Path) -> None:
drop(tmp_path / "round", "n500-vegbygging.md")
run(tmp_path, profile=STRUCTURED_V1)
assert not (tmp_path / "bundle" / "index.md").read_text(encoding="utf-8").startswith("---")
# --- emission -------------------------------------------------------------
def test_the_root_index_opens_with_the_declared_bundle_id(tmp_path: Path) -> None:
drop(tmp_path / "round", "n500-vegbygging.md")
run(tmp_path, values={"bundle_id": "b-1"})
body = (tmp_path / "bundle" / "index.md").read_text(encoding="utf-8")
assert body.startswith("---\nbundle_id: b-1\n---\n\n")
def test_the_value_is_written_verbatim_and_unquoted(tmp_path: Path) -> None:
# Read as RAW BYTES: a parsed assertion returns the same string whether or
# not the emitter added quotes, so it would mask exactly the defect a
# consumer's shape gate trips on.
drop(tmp_path / "round", "n500-vegbygging.md")
run(tmp_path, values={"bundle_id": "svv-n500-2026"})
assert b"bundle_id: svv-n500-2026\n" in (tmp_path / "bundle" / "index.md").read_bytes()
def test_a_second_round_does_not_double_the_block(tmp_path: Path) -> None:
drop(tmp_path / "one", "n500-vegbygging.md")
run(tmp_path, values={"bundle_id": "b-1"}, round_name="one")
drop(tmp_path / "two", "v720-tunnel.md")
run(tmp_path, values={"bundle_id": "b-1"}, round_name="two")
body = (tmp_path / "bundle" / "index.md").read_text(encoding="utf-8")
assert body.startswith("---\nbundle_id: b-1\n---\n\n")
assert body.count("bundle_id:") == 1
def test_the_index_still_carries_its_entries_below_the_block(tmp_path: Path) -> None:
drop(tmp_path / "round", "n500-vegbygging.md")
run(tmp_path, values={"bundle_id": "b-1"})
body = (tmp_path / "bundle" / "index.md").read_text(encoding="utf-8")
assert "](inbox-n500-vegbygging.md)" in body
assert body.index("bundle_id") < body.index("](inbox-n500-vegbygging.md)")
# --- fail-fast, before any disk mutation ----------------------------------
def test_a_key_the_policy_does_not_name_is_refused_before_any_write(tmp_path: Path) -> None:
drop(tmp_path / "round", "n500-vegbygging.md")
before = tree(tmp_path / "bundle")
with pytest.raises(MaterializationError) as excinfo:
run(tmp_path, values={"okf_version": "0.2"})
assert excinfo.value.code == "index_root_frontmatter_unexpected"
# The whole point of hoisting the call above the write: a refused run must
# leave nothing behind, not a half-built bundle whose index is missing.
assert tree(tmp_path / "bundle") == before
assert before == {}
def test_a_refusal_leaves_an_existing_bundle_untouched(tmp_path: Path) -> None:
drop(tmp_path / "one", "n500-vegbygging.md")
run(tmp_path, values={"bundle_id": "b-1"}, round_name="one")
before = tree(tmp_path / "bundle")
assert before != {}
drop(tmp_path / "two", "v720-tunnel.md")
with pytest.raises(MaterializationError) as excinfo:
run(tmp_path, values={"okf_version": "0.2"}, round_name="two")
assert excinfo.value.code == "index_root_frontmatter_unexpected"
assert tree(tmp_path / "bundle") == before
def test_values_are_refused_against_a_profile_naming_no_root_keys(tmp_path: Path) -> None:
drop(tmp_path / "round", "n500-vegbygging.md")
with pytest.raises(MaterializationError) as excinfo:
run(tmp_path, profile=DEFAULT, values={"bundle_id": "b-1"})
assert excinfo.value.code == "index_root_frontmatter_unexpected"
assert tree(tmp_path / "bundle") == {}