"""The proving consumer's contract as a profile (Phase 3, step 3). `STRICT_V1` is the `claude-code-llm-wiki` bundle contract expressed in the same object `DEFAULT` uses. Everything pinned here was measured in their repository on 2026-07-25 and settled in `docs/phase-3-split-table.md`; the eight-key required set is their operator's ratification, deliberately stricter than the four-key constant their own validator enforces. These tests are also the reader that earns the new schema fields. A profile field no code reads is a claim no test covers, so `required`, `allowed`, `nullable` and `key_pattern` land together with `FrontmatterSchema.violations`, which is what reads them. What is NOT here, and why: `violations` takes an already-parsed mapping. This library's line-oriented parser cannot represent the block lists and nulls the consumer's frontmatter admits — that is precisely why Door C writes imported concepts verbatim — so parsing strict-v1 frontmatter is a separate concern from judging it, and lands separately. """ from __future__ import annotations import pytest from llm_ingestion_okf.profiles import ( DEFAULT, STRICT_V1, FrontmatterSchema, ) # The eight keys the consumer's operator ratified on 2026-07-25, measured # present on 522/522 of their documents. RATIFIED_REQUIRED = frozenset( { "type", "title", "description", "timestamp", "layer", "source_tier", "source_url", "source_sha", } ) # `FRONTMATTER_KEY_ORDER` in their `bundle.py`: the eight above plus three # layer-specific keys, doubling as canonical emission order. RATIFIED_ORDER = ( "type", "title", "description", "timestamp", "layer", "source_tier", "source_url", "source_sha", "version", "date", "summary", ) def wiki_document() -> dict[str, object]: """A conforming `concepts/` page, every allowlisted key present.""" return { "type": "Concept", "title": "Hooks", "description": "Event-driven automation in Claude Code.", "timestamp": "2026-07-25T12:00:00Z", "layer": "concepts", "source_tier": "official-docs", "source_url": "https://docs.claude.com/en/docs/claude-code/hooks", "source_sha": "0" * 64, "version": "2.1.183", "date": "2026-07-25", "summary": "What hooks are and when they fire.", } def codes(schema: FrontmatterSchema, values: dict[str, object]) -> list[str]: return [violation.code for violation in schema.violations(values)] # --- the profile itself --------------------------------------------------- def test_strict_v1_closes_the_type_enum_to_the_four_document_classes() -> None: """Their four classes exactly — an open set would admit anything.""" assert STRICT_V1.types.allowed == frozenset({"Concept", "Guide", "Reference", "Release"}) def test_strict_v1_requires_the_eight_ratified_keys() -> None: """Eight, not the four their `REQUIRED_KEYS` constant spells. Their constant is the emit-path minimum; the contract their operator ratified is all eight. This is the one place the profile is deliberately stricter than the consumer's own validator, and the agreed resolution if a document class ever legitimately lacks `source_sha` is to bump the profile, not to bend the bundle. """ assert STRICT_V1.frontmatter.required == RATIFIED_REQUIRED def test_strict_v1_allowlist_is_eleven_keys_and_doubles_as_emission_order() -> None: """The allowlist and the order are one list, not two that can drift apart. Their `BUNDLE_HASH_REGISTRY` gate depends on regeneration being byte-identical, which is what the fixed order buys. """ assert STRICT_V1.frontmatter.order == RATIFIED_ORDER assert STRICT_V1.frontmatter.allowed == frozenset(RATIFIED_ORDER) def test_the_three_layer_specific_keys_are_optional_not_required() -> None: """`version`/`date` sit on 351/522 documents and `summary` on 349/522. Requiring them would reject pages the consumer ships today. """ allowed = STRICT_V1.frontmatter.allowed assert allowed is not None for key in ("version", "date", "summary"): assert key in allowed assert key not in STRICT_V1.frontmatter.required def test_summary_is_the_only_nullable_key() -> None: """The single deliberate escape from strings-only frontmatter.""" assert STRICT_V1.frontmatter.nullable == frozenset({"summary"}) # --- the reader: a conforming document ----------------------------------- def test_a_conforming_wiki_document_has_no_violations() -> None: assert STRICT_V1.frontmatter.violations(wiki_document()) == () def test_the_optional_keys_may_simply_be_absent() -> None: """A `concepts/` page carries neither `version` nor `date`.""" document = wiki_document() for key in ("version", "date", "summary"): del document[key] assert STRICT_V1.frontmatter.violations(document) == () # --- the reader: cross-profile rejection --------------------------------- def test_a_door_a_ingest_document_is_rejected_under_strict_v1() -> None: """The plan's cross-profile test, frontmatter half. A bundle this library generates under `DEFAULT` carries the ingest-spec layer, which shares only `type` and `title` with the consumer's contract: six required keys are missing and five of its own keys are off-allowlist. """ door_a = { "type": "dataset", "title": "Orders", "source_system": "golden-catalogue", "source_query": "orders.csv", "ingested_at": "2026-07-16T12:00:00Z", "ingest_manifest": "manifest@37674ac20059e788", "generated": "true", } violations = STRICT_V1.frontmatter.violations(door_a) assert violations != () missing = {v.key for v in violations if v.code == "frontmatter_key_missing"} assert missing == RATIFIED_REQUIRED - {"type", "title"} off_allowlist = {v.key for v in violations if v.code == "frontmatter_key_not_allowed"} assert off_allowlist == { "source_system", "source_query", "ingested_at", "ingest_manifest", "generated", } def test_default_judges_nothing_about_keys_so_both_doors_stay_valid() -> None: """`DEFAULT` must NOT grow a required set — measured, not assumed. Door A emits seven keys, Door B six, and Door C writes an imported concept verbatim with whatever frontmatter the sender wrote. A required set on `DEFAULT` would therefore declare invalid the very bundles this library produces. `DEFAULT` keeps an open namespace; the rejection of a wiki-shaped bundle under `DEFAULT` comes from the index and path shape instead. """ assert DEFAULT.frontmatter.required == frozenset() assert DEFAULT.frontmatter.allowed is None assert DEFAULT.frontmatter.violations(wiki_document()) == () assert DEFAULT.frontmatter.violations({"type": "dataset", "title": "Orders"}) == () # --- the reader: each check ---------------------------------------------- def test_a_missing_required_key_is_named_individually() -> None: document = wiki_document() del document["source_sha"] violations = STRICT_V1.frontmatter.violations(document) assert [(v.key, v.code) for v in violations] == [("source_sha", "frontmatter_key_missing")] def test_a_key_outside_the_allowlist_is_refused() -> None: """A closed allowlist is what makes the contract enumerable at all.""" document = wiki_document() document["author"] = "someone" assert codes(STRICT_V1.frontmatter, document) == ["frontmatter_key_not_allowed"] def test_a_key_name_outside_the_grammar_is_refused() -> None: """`^[a-z_]+$`: a key that reaches the allowlist check malformed would otherwise be reported only as 'not allowed', which hides the real defect.""" schema = FrontmatterSchema(order=("type",), key_pattern=STRICT_V1.frontmatter.key_pattern) violations = schema.violations({"Source-URL": "x"}) assert [(v.key, v.code) for v in violations] == [("Source-URL", "frontmatter_key_malformed")] def test_summary_may_be_null_and_no_other_key_may() -> None: document = wiki_document() document["summary"] = None assert STRICT_V1.frontmatter.violations(document) == () document["description"] = None assert [(v.key, v.code) for v in STRICT_V1.frontmatter.violations(document)] == [ ("description", "frontmatter_value_null") ] def test_a_non_empty_list_of_strings_is_a_legal_value() -> None: """The block-list shape their `Release` pages carry. A profile that assumed scalars-only would reject the consumer's own pages — and a parser that assumed scalars-only would silently destroy them, which is why Door C writes imported concepts verbatim. """ document = wiki_document() document["source_url"] = ["https://a.example/one", "https://a.example/two"] assert STRICT_V1.frontmatter.violations(document) == () @pytest.mark.parametrize( "value", [[], ["ok", 3], {"nested": "map"}, 7, True], ids=["empty-list", "list-with-non-string", "mapping", "int", "bool"], ) def test_a_value_outside_the_scalar_or_string_list_shape_is_refused(value: object) -> None: document = wiki_document() document["title"] = value assert [(v.key, v.code) for v in STRICT_V1.frontmatter.violations(document)] == [ ("title", "frontmatter_value_shape") ] # --- determinism and construction-time invariants ------------------------- def test_violations_come_back_in_a_deterministic_order() -> None: """Two runs over the same document must report identically ordered. Determinism is bit-exact in this library; a violation list that depended on mapping insertion order would make a report irreproducible. """ document = wiki_document() del document["source_sha"] del document["layer"] document["zzz"] = "off-allowlist" document["aaa"] = "off-allowlist" reported = [(v.key, v.code) for v in STRICT_V1.frontmatter.violations(document)] assert reported == sorted(reported) reversed_document = dict(reversed(list(document.items()))) assert [ (v.key, v.code) for v in STRICT_V1.frontmatter.violations(reversed_document) ] == reported def test_a_required_key_outside_the_allowlist_cannot_be_constructed() -> None: """An unsatisfiable schema is a defect in the profile, not in a document.""" with pytest.raises(ValueError, match="required"): FrontmatterSchema( order=("type", "title"), required=frozenset({"type", "absent_from_allowlist"}), allowed=frozenset({"type", "title"}), ) def test_a_nullable_key_outside_the_allowlist_cannot_be_constructed() -> None: with pytest.raises(ValueError, match="nullable"): FrontmatterSchema( order=("type",), allowed=frozenset({"type"}), nullable=frozenset({"summary"}), ) def test_strict_v1_path_namespaces_are_the_spec_namespaces() -> None: """The door filename prefixes are an ingest-spec invariant, not a preference. They describe what Doors A/B/C write, so they are the same under any profile; the consumer's own files are written by their pipeline, not by a door, and are unaffected either way. """ assert STRICT_V1.paths == DEFAULT.paths def test_strict_v1_index_policy_is_the_consumers_shape() -> None: """The gap this test used to pin is closed; it now states the shape. Every value is read out of their code rather than recalled — the entry template and the root/nested frontmatter split from `bundle.py:498-567`, the bidirectional match from gate `BUNDLE_INDEX_COMPLETE` (`validate.py:1081-1120`, severity ERROR). The reader that judges all of it lives on `IndexPolicy.violations`, so no field here is written without something that reads it. """ index = STRICT_V1.index assert index != DEFAULT.index assert index.name == DEFAULT.index.name assert index.render_link("Hooks", "hooks.md", "How hooks fire.") == ( "* [Hooks](hooks.md) - How hooks fire." ) assert index.per_directory is True assert index.heading_required is True assert index.allows_prose is False assert index.entries_match_directory is True assert index.root_frontmatter == ("okf_version", "bundle_profile", "okf_spec_commit") def test_a_conforming_wiki_root_index_passes_and_a_default_one_does_not() -> None: """The plan's second cross-profile test: a bundle valid under one profile is refused by the other. It could not come from frontmatter — DEFAULT has no required key set, by measurement — so it comes from index shape. """ conforming = ( "---\nokf_version: 0.1\nbundle_profile: strict-v1\n" "okf_spec_commit: d44368c\n---\n\n# Wiki\n\n" "* [Concepts](concepts/index.md) - Machine-generated index of concepts.\n" ) assert ( STRICT_V1.index.violations(conforming, is_root=True, expected_targets={"concepts/index.md"}) == () ) default_shaped = "# Wiki\n\nCurated prose.\n\n- [Concepts](concepts/index.md)\n" codes = { violation.code for violation in STRICT_V1.index.violations( default_shaped, is_root=True, expected_targets={"concepts/index.md"} ) } assert codes == { "index_root_key_missing", "index_prose_not_allowed", "index_entry_missing", } # ...and the reverse direction: DEFAULT judges neither of them, because a # judging default would condemn the bundles this library itself writes. assert DEFAULT.index.violations(conforming, is_root=True) == () assert DEFAULT.index.violations(default_shaped, is_root=True) == () def test_strict_v1_emission_is_the_ordered_prefix_then_the_sorted_tail() -> None: """Commons decision D1, unchanged by the stricter namespace.""" emitted = STRICT_V1.frontmatter.emit( {"title": "Hooks", "type": "Concept", "description": "d", "timestamp": "t"} ) assert emitted == "type: Concept\ntitle: Hooks\ndescription: d\ntimestamp: t"