fix(profiles): P1-F1 — a permitted root key is not a required one

`IndexPolicy.root_frontmatter` carried two claims at once: which keys the
root index may carry and in what order, and which it must carry. The judge
read it as the second, so `OKF_V0_2` — which names `okf_version` only to fix
its position, upstream granting it as a MAY (§8:509-510, §12:773-775) —
reported every bundle exercising that MAY as violating. Measured in P1 over
17 bundles: 14 failed with exactly this one violation, upstream's own four
reference bundles among them, while D5's emitter treated the same key as
optional. We emitted a MAY correctly and graded it a MUST.

`root_frontmatter` now permits and orders; `root_frontmatter_required`
demands. A required key outside the ordered set fails at construction, the
same contradiction `FrontmatterSchema` already refuses when `required`
strays outside `allowed`.

- `OKF_V0_2` requires none — upstream's MAY, stated on the judge side too.
- `STRICT_V1` requires all three: the proving consumer's root index carries
  exactly those keys in that order on every bundle measured (`c5141f8`), so
  separating the meanings costs them nothing.
- `DEFAULT` names no root keys and is untouched.

Re-measured over the eight bundle-root indexes reachable locally (our four
goldens, upstream's four): 7 of 8 failing under the old semantics, 0 of 8
after. Emit path byte-identical — the golden suite fails otherwise.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqCmfJ2ukpFXeFjfab8wvy
This commit is contained in:
Kjell Tore Guttormsen 2026-07-31 18:16:13 +02:00
commit 2c01e58259
2 changed files with 85 additions and 5 deletions

View file

@ -32,7 +32,7 @@ import re
import pytest
from llm_ingestion_okf.profiles import DEFAULT, STRICT_V1, IndexPolicy
from llm_ingestion_okf.profiles import DEFAULT, OKF_V0_2, STRICT_V1, IndexPolicy
# --- DEFAULT keeps the Phase 1/2 shape (assumption C1) --------------------
@ -238,6 +238,60 @@ def test_the_pinned_keys_are_ordered_not_merely_present() -> None:
assert [v.code for v in found] == ["index_root_key_order"]
# --- P1-F1: permitted-and-ordered is not the same claim as required -------
def test_a_permitted_root_key_may_be_omitted_without_a_finding() -> None:
"""P1-F1, measured 2026-07-31: `OKF_V0_2` names `okf_version` because
upstream §8/§12 say a bundle-root index MAY carry it a permission, not a
demand. Judging the key as required made 14 of the 17 bundles swept fail
with exactly this one violation, upstream's own four reference bundles
among them, while D5's emitter treats the same key as optional (omitting
`root_frontmatter_values` writes no block). We emitted a MAY correctly and
graded it a MUST."""
text = "# Bundle\n\n- [Sales](ingest-sales.md)\n"
assert OKF_V0_2.index.violations(text, is_root=True) == ()
def test_the_permitted_key_is_still_ordered_and_still_root_only() -> None:
"""Separating the two meanings must not cost the checks that were right:
a nested index carrying the key is still a finding, and a root index that
carries it is still judged for order."""
nested = OKF_V0_2.index.violations("---\nokf_version: 0.2\n---\n\n# Concepts\n")
assert [(v.subject, v.code) for v in nested] == [
("okf_version", "index_root_frontmatter_unexpected")
]
root = OKF_V0_2.index.violations("---\nokf_version: 0.2\n---\n\n# Bundle\n", is_root=True)
assert root == ()
def test_a_required_root_key_is_still_reported_when_absent() -> None:
"""`STRICT_V1` mirrors the proving consumer's ratified contract, which
demands all three (they emit all three measured across their bundle at
`c5141f8`). The fix separates the meanings; it does not relax them."""
found = STRICT_V1.index.violations(
"---\nokf_version: 0.1\n---\n\n# Wiki\n", is_root=True, expected_targets=set()
)
assert [(v.subject, v.code) for v in found] == [
("bundle_profile", "index_root_key_missing"),
("okf_spec_commit", "index_root_key_missing"),
]
def test_a_required_key_outside_the_ordered_set_fails_at_construction() -> None:
"""A key demanded but never named in the ordered tuple could never be
judged for position the same contradiction `FrontmatterSchema` refuses
when `required` strays outside `allowed`."""
with pytest.raises(ValueError, match="ordered"):
IndexPolicy(
name="index.md",
link_template="- [{label}]({target})",
link_pattern=DEFAULT.index.link_pattern,
root_frontmatter=("okf_version",),
root_frontmatter_required=frozenset({"bundle_profile"}),
)
def test_a_nested_index_carries_no_frontmatter_at_all() -> None:
"""Confirmed independently in two consumers: the wiki writes frontmatter
only at the bundle root (`bundle.py:544-557`), and the catalog reports