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:
parent
8f9b4c8cca
commit
f65f5fc342
8 changed files with 80 additions and 8 deletions
|
|
@ -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]"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue