"""`okf build` runs a NAMED gate, and the bundle says which one (F1). Reported from outside on 2026-09-15 by `claude-code-llm-wiki`, verified here before a line moved: `corpus.measure` wired an unconditional approve-everything stub (`corpus._gate`, returning the persist disposition for any text) into `process_inbox`, and no `add_argument` call anywhere in the package named a gate. So the only path people actually use -- `okf build`, and `okf project` through it -- screened nothing, while `pyproject.toml` makes the guard a MANDATORY runtime dependency and the README recommends exactly the composition that was never reachable. A permissive stub that approves everything is the shape this repository's own README names as the danger; it was on our own door. Three separate things are pinned, because they fail in three different ways: - **the gate runs.** A document the real guard refuses is not persisted. Under the stub it was, which is the defect itself; `CARRIER` is measured to fail secure in BOTH presets (an invisible carrier is an any-tier finding), so this test cannot pass by picking a lenient tier. - **the gate is named in the artifact.** SS 9's `log.md` already carries `N` because it is the one fact about a run the bundle cannot otherwise recover. Which gate screened the bytes is the same class of fact: without it a bundle built with `--gate none` is indistinguishable from one the guard cleared, and that indistinguishability is the whole trust trap, not the stub alone. - **the seam composes with segmentation.** Measured before the fix: `grep -rl inbox_gate tests/` gave ONE file (`tests/test_guard_adapter.py`) and `grep -c segment` in it gave 0, while the nine files passing `segmentation=`/`segmentations=` all injected a local warn-stub. The composition the README recommends -- `process_inbox(segmentations=..., gate=inbox_gate)` -- had no test at all, which is how the defect survived. The default is `guard-trusted-source`, set by the operator 2026-09-15 on a measurement rather than on caution: over the 453 concept bodies of the pinned default bundle, `PRESET_TRUSTED_SOURCE` returns the persist disposition on 453 of 453 (the artifact survives the move), while `PRESET_USER_UPLOAD` holds 1 of them and would take one of the 39 source documents out of the bundle. Pointing `okf build` at your own folder is not an untrusted upload; Door B's library default stays `PRESET_USER_UPLOAD` because an inbox drop is. """ from __future__ import annotations from pathlib import Path import pytest from llm_ingestion_okf import cli, corpus from llm_ingestion_okf.inbox import process_inbox from llm_ingestion_okf.profiles import SEGMENTED_OKF_V0_2 from llm_ingestion_okf.propose import build_plan from llm_ingestion_okf.segmentation import parse_segmentation_plan BUNDLE_ID = "cli-gate-fixture" OKF_VERSION = "0.2" INGESTED_AT = "2026-09-15T00:00:00Z" # Measured against the pinned guard 1.4.0, both presets, before this suite was # written: `fail_secure` under `PRESET_TRUSTED_SOURCE` AND under # `PRESET_USER_UPLOAD` ("any-tier: invisible carrier"). A fixture only one tier # refuses would make this suite pass for the wrong reason. CARRIER = "# Kostnader\n\nEn merknad med et nullbredde​tegn i seg.\n" BENIGN = "# Kostnader\n\nKvartalstall for plattformgruppen, uten funn.\n" def _inbox(root: Path, documents: dict[str, str]) -> Path: inbox = root / "inbox" inbox.mkdir(parents=True, exist_ok=True) for name, body in documents.items(): (inbox / name).write_text(body, encoding="utf-8", newline="") return inbox def _build(inbox: Path, bundle: Path, *extra: str) -> int: return cli.main( [ "build", str(inbox), "--bundle", str(bundle), "--bundle-id", BUNDLE_ID, "--okf-version", OKF_VERSION, *extra, ] ) def _concepts(bundle: Path) -> list[Path]: return [ path for path in sorted(bundle.rglob("*.md")) if path.name not in {"index.md", corpus.LOG_NAME} ] # --- the gate runs --------------------------------------------------------- def test_build_refuses_a_document_the_real_guard_refuses(tmp_path: Path) -> None: """The defect itself, as a red test: the stub persisted this document. `CARRIER` carries a zero-width space inside a word. The guard refuses it in any trust tier, so a build that persists it has not consulted the guard -- whatever the dependency table says. """ pytest.importorskip("llm_ingestion_guard") inbox = _inbox(tmp_path, {"carrier.md": CARRIER}) bundle = tmp_path / "bundle" assert _build(inbox, bundle) == 0 assert _concepts(bundle) == [], "a document the guard refuses must not reach the bundle" def test_build_persists_a_document_the_real_guard_clears(tmp_path: Path) -> None: """The known-positive beside it: the gate must not simply refuse everything. A gate that blocked every document would pass the test above and destroy the command. Both halves are needed, on the same default, in the same run. """ pytest.importorskip("llm_ingestion_guard") inbox = _inbox(tmp_path, {"benign.md": BENIGN}) bundle = tmp_path / "bundle" assert _build(inbox, bundle) == 0 assert _concepts(bundle), "a clean document must still reach the bundle" def test_gate_none_is_reachable_and_still_permissive(tmp_path: Path) -> None: """`--gate none` keeps the old behaviour, deliberately and by name. The stub is not deleted -- the corpus harness reproduces published numbers with it, and a caller measuring segmentation alone has a legitimate reason to take the gate out of the picture. What changes is that asking for it is now an act, and the bundle records it. """ inbox = _inbox(tmp_path, {"carrier.md": CARRIER}) bundle = tmp_path / "bundle" assert _build(inbox, bundle, "--gate", "none") == 0 assert _concepts(bundle), "--gate none is the documented permissive path" def test_user_upload_preset_is_reachable(tmp_path: Path) -> None: """The stricter tier is a flag value, not a fork of the adapter. Door B's own default stays `PRESET_USER_UPLOAD`; the CLI exposes it so a caller whose folder IS an untrusted drop does not have to write their own entry point to reach the tier this library already ships. """ pytest.importorskip("llm_ingestion_guard") inbox = _inbox(tmp_path, {"benign.md": BENIGN}) bundle = tmp_path / "bundle" assert _build(inbox, bundle, "--gate", "guard-user-upload") == 0 assert _concepts(bundle) def test_an_unknown_gate_name_is_refused(tmp_path: Path) -> None: """A misspelled tier must not fall back to the permissive one. Falling back would reproduce the defect with an extra step: the caller believes they asked for the guard, and the run approves everything. """ inbox = _inbox(tmp_path, {"benign.md": BENIGN}) bundle = tmp_path / "bundle" with pytest.raises(SystemExit): _build(inbox, bundle, "--gate", "guard-trusted") assert not bundle.exists() or not _concepts(bundle) # --- the gate is named in the artifact ------------------------------------- def test_the_log_names_the_gate_that_screened_the_bundle(tmp_path: Path) -> None: """SS 9's log carries the gate for the same reason it carries `N`. A consumer holding a bundle cannot otherwise tell a screened one from an unscreened one, and that is the trust trap in its pure form -- a stub is only dangerous because nothing downstream can see it. """ pytest.importorskip("llm_ingestion_guard") inbox = _inbox(tmp_path, {"benign.md": BENIGN}) bundle = tmp_path / "bundle" assert _build(inbox, bundle) == 0 log = (bundle / corpus.LOG_NAME).read_text(encoding="utf-8") assert corpus.GATE_GUARD_TRUSTED_SOURCE in log def test_the_log_says_when_nothing_was_screened(tmp_path: Path) -> None: """`--gate none` must be legible as "nothing was screened", not as silence. An omitted line reads as "no gate section in this log format"; a present line naming the permissive stub reads as what it is. """ inbox = _inbox(tmp_path, {"benign.md": BENIGN}) bundle = tmp_path / "bundle" assert _build(inbox, bundle, "--gate", "none") == 0 log = (bundle / corpus.LOG_NAME).read_text(encoding="utf-8") assert corpus.GATE_NONE in log assert "NOTHING WAS SCREENED" in log def test_every_gate_name_renders_a_log_line() -> None: """No gate name may render a log without a gate line. A name added later without a description would produce a bundle that declares its gate as the empty string, which reads as an absent field. """ for name in corpus.GATE_NAMES: report = corpus.CorpusReport( corpus="corpus", ingested_at=INGESTED_AT, n=0, extracted=0, gated=0, persisted=0, substantive=0, degenerate=0, rejected=0, seconds_total=0.0, converter_path="none", converter_version="none", codes=(), unaccounted=(), gate=name, ) assert f"**Gate**: {name}" in report.render_log() # --- the seam composes with segmentation ----------------------------------- def test_segmentation_and_the_real_guard_compose(tmp_path: Path) -> None: """`process_inbox(segmentations=..., gate=inbox_gate)`, the README's own form. Measured before this test existed: no test in the repository ran a real guard verdict and a segmentation plan in the same call. The composition is what the README recommends to consumers, so leaving it untested left the recommendation unverified -- and it is the exact call `okf build` now makes. """ guard_adapter = pytest.importorskip("llm_ingestion_okf.guard_adapter") document = ( "# 1 Innledning\n\nDette dokumentet beskriver krav til seksjonering.\n\n" "# 2 Omfang\n\nOmfanget er hele anlegget og alle tilhoerende systemer.\n" ) inbox = _inbox(tmp_path, {"alpha.md": document}) bundle = tmp_path / "bundle" source = inbox / "alpha.md" plans = { "alpha.json": parse_segmentation_plan( build_plan( source, document, source.read_bytes(), okf_type="reference", proposed_at=INGESTED_AT, path_prefix="alpha", ) ) } result = process_inbox( inbox, bundle, INGESTED_AT, okf_type="reference", gate=guard_adapter.inbox_gate, profile=SEGMENTED_OKF_V0_2, root_frontmatter_values={"okf_version": OKF_VERSION, "bundle_id": BUNDLE_ID}, segmentations=plans, ) assert len(result.persisted) == 1 assert not result.rejected and not result.quarantined assert len(_concepts(bundle)) > 1, "the plan's segments must be what the guard screened" def test_segmentation_and_the_real_guard_refuse_together(tmp_path: Path) -> None: """The known-negative for the composition above, on the same call shape. One refused segment body refuses the whole file, which is Door B's stated rule; without this half the test above would pass against a gate that never said no. """ guard_adapter = pytest.importorskip("llm_ingestion_okf.guard_adapter") document = ( "# 1 Innledning\n\nDette dokumentet beskriver krav til seksjonering.\n\n" "# 2 Omfang\n\nEn merknad med et nullbredde​tegn i seg.\n" ) inbox = _inbox(tmp_path, {"alpha.md": document}) bundle = tmp_path / "bundle" source = inbox / "alpha.md" plans = { "alpha.json": parse_segmentation_plan( build_plan( source, document, source.read_bytes(), okf_type="reference", proposed_at=INGESTED_AT, path_prefix="alpha", ) ) } result = process_inbox( inbox, bundle, INGESTED_AT, okf_type="reference", gate=guard_adapter.inbox_gate, profile=SEGMENTED_OKF_V0_2, root_frontmatter_values={"okf_version": OKF_VERSION, "bundle_id": BUNDLE_ID}, segmentations=plans, ) assert not result.persisted assert result.rejected, "a carrier in one segment refuses the file" # --- the adapter's second tier --------------------------------------------- def test_the_trusted_source_adapter_is_the_same_shape(tmp_path: Path) -> None: """The second tier is a second three-line adapter, not a parameter. `guard_adapter`'s own docstring says a caller needing another tier writes their own three-line adapter; this is that adapter, shipped, so the CLI does not have to reach past the seam into the guard's presets. """ guard_adapter = pytest.importorskip("llm_ingestion_okf.guard_adapter") clean = guard_adapter.inbox_gate_trusted_source(BENIGN) assert clean.disposition == "warn" assert clean.sanitized_text == BENIGN held = guard_adapter.inbox_gate_trusted_source(CARRIER) assert held.disposition != "warn", "an any-tier finding is refused at every tier" assert held.reasons, "the guard's audit trail is carried across verbatim"