fix(inbox): a segment title is declared, never marked derived

A segment's title comes from the plan, so a human adjudicated it. But
structure derivation runs over the segment body, finds no title key and
no usable heading, falls back to a stem, and adds "title" to derived.
The concept then emitted a stated fact under an inferred marker, and a
consumer that distrusts derived fields would distrust exactly the thing
a human decided. An over-marked field is the same defect class as an
unmarked heuristic: the marker is only worth something if it is
accurate in both directions.

Scoped to title alone, and pinned that way by test: number stays in
derived on a segment, because nothing about segmentation makes an
inferred document number declared. Without a segment a derived title is
still marked, so only a plan makes a title declared.

The SEGMENTED_V1 golden moves, which is the intended consequence and
the only golden that may. The four existing goldens are byte-identical
to baseline 770d8d4, measured against the sha rather than inspected.

Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-01 19:29:46 +02:00
commit f65f5fc342
8 changed files with 80 additions and 8 deletions

View file

@ -29,6 +29,7 @@ from llm_ingestion_okf.errors import MaterializationError
from llm_ingestion_okf.inbox import GateDecision, process_inbox, render_inbox_concept
from llm_ingestion_okf.profiles import DEFAULT, SEGMENTED_V1, STRUCTURED_V1
from llm_ingestion_okf.segmentation import SegmentEntry, parse_segmentation_plan
from llm_ingestion_okf.structure import derive_document_structure
INGESTED_AT = "2026-07-25T12:00:00Z"
@ -213,7 +214,8 @@ def render(**overrides: object) -> str:
"profile": SEGMENTED_V1,
}
arguments.update(overrides)
return render_inbox_concept(DOCUMENT, **arguments) # type: ignore[arg-type]
text = arguments.pop("text", DOCUMENT)
return render_inbox_concept(text, **arguments) # type: ignore[arg-type]
def frontmatter_of(document: str) -> dict[str, str]:
@ -336,3 +338,66 @@ def test_two_bundles_hold_colliding_paths_and_disjoint_identity_values() -> None
assert [frontmatter_of(document)["bundle_id"] for document in one] == ["b-1", "b-1"]
assert [frontmatter_of(document)["bundle_id"] for document in other] == ["b-2", "b-2"]
assert set(one).isdisjoint(set(other))
# --- `derived` never marks a title the adjudicator declared ---------------
#
# The second measured defect. A segment's `title` comes from the PLAN, which a
# human adjudicated; but structure derivation runs over the segment BODY, finds
# no `title` key and no usable heading, falls back, and adds `title` to
# `derived`. The concept then emits the declared title and marks it inferred.
# The error points the wrong way: a consumer that distrusts derived fields ends
# up distrusting a fact the producer stated. Marking is only worth anything if
# it is accurate in both directions, so an over-marked field is the same defect
# class as an unmarked heuristic.
def structure_of(text: str, source_file: str = "veiledning.md"):
return derive_document_structure(text, source_file=source_file)
def test_a_segment_title_is_never_marked_derived() -> None:
body = "## 1.1 Foerste krav\n\nEt krav.\n"
assert "title" in structure_of(body).derived # the premise, measured
keys = frontmatter_of(
render(
text=body,
title="Foerste krav",
structure=structure_of(body),
segment=segment_entry(),
bundle_id="b-1",
)
)
assert keys["title"] == "Foerste krav"
assert "derived" not in keys
def test_a_genuinely_derived_field_is_still_marked_on_a_segment() -> None:
"""Scoped to `title` alone -- the fix must not blunt the marker.
`number` here IS inferred from the body, and nothing about segmentation
makes it declared, so it must survive in `derived`.
"""
body = "# N500 Vegtunneler\n\nSe N100.\n"
derived = structure_of(body, "n500.md").derived
assert {"title", "number"} <= derived # the premise, measured
keys = frontmatter_of(
render(
text=body,
title="Vegtunneler",
structure=structure_of(body, "n500.md"),
segment=segment_entry(),
bundle_id="b-1",
)
)
assert "title" not in keys["derived"]
assert "number" in keys["derived"]
def test_without_a_segment_a_derived_title_is_still_marked() -> None:
"""The negative control. Only a PLAN makes a title declared."""
body = "## 1.1 Foerste krav\n\nEt krav.\n"
keys = frontmatter_of(
render(text=body, title="Foerste krav", structure=structure_of(body), profile=STRUCTURED_V1)
)
assert keys["derived"] == "[title]"