llm-ingestion-okf/tests/test_packaging.py
Kjell Tore Guttormsen e60f7261a1 build(deps): move the guard pin from >=0.3,<0.4 to >=1.2,<2.0
The operator's condition for revisiting the pin was met (v1.2.0 contains
the flow-mapping frontmatter fix, commit 5870483) and the operator has now
approved the move itself, dispatched as its own order because it changes
consumer-visible Requires-Dist and shifts golden-fixture admission.

Floor 1.2: this library needs the flow-mapping support (`generated: { by:
x, at: y }`) that landed there — without it Door C fail-secures every
concept carrying that stamp. Ceiling <2.0, not narrower: the guard's own
1.0.0 release freezes its exported surface until a 2.0.0, and explicitly
keeps calibration (severities, dispositions) free to move within 1.x, so a
tighter ceiling here would claim a stability guarantee neither side needs.

Re-measured through Door C against the guard's own default
(allow_reserved=True, matching how the earlier recommendation measured
it), over the 9 concept documents across all four Door-A goldens:
4/9 admitted at 0.3.4 -> 8/9 admitted at 1.2.0, confirming the number
already reported. The ninth (a `sources` block-list carrying `resource`)
stays refused by design (G30) and is not expected to move.

Failing-test-first: test_guard_adapter.py::test_guard_version_is_inside_the_pin
and test_packaging.py::test_the_only_runtime_dependency_is_the_security_boundary
were updated to the new pin first and confirmed red against the
still-installed 0.3.4, then `uv sync --extra extract` installed 1.2.0 and
both went green. Full suite (615), ruff and mypy --strict clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxcxzNwpX1kDP53n1rLhM5
2026-08-23 21:05:18 +02:00

64 lines
2.8 KiB
Python

"""Packaging contract: a PEP 561 typed package with exactly one dependency.
Consumers run mypy --strict against the inline annotations; without the
py.typed marker mypy degrades every imported symbol to Any.
"""
from __future__ import annotations
from pathlib import Path
import pytest
import llm_ingestion_okf
PROJECT_ROOT = Path(__file__).resolve().parents[1]
def test_package_ships_py_typed_marker() -> None:
package_dir = Path(llm_ingestion_okf.__file__).parent
assert (package_dir / "py.typed").is_file()
def test_the_only_runtime_dependency_is_the_security_boundary() -> None:
"""The stdlib-only rule, enforced rather than asserted in prose.
One dependency is permitted — the guard — because security is the one
thing this library must not implement. Everything else stays stdlib, so
a consumer vendoring this package takes on no transitive surface. The
version RANGE is the pin: it resolves against a package index, and is
satisfied by the git+https tag install until that index exists.
"""
tomllib = pytest.importorskip("tomllib") # stdlib from 3.11; the pin holds on 3.10 too
pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8"))
assert pyproject["project"]["dependencies"] == ["llm-ingestion-guard>=1.2,<2.0"]
def test_the_declared_version_agrees_with_the_packaged_one() -> None:
"""The two places a version is written must not drift apart.
The install channel is a direct git reference, so a consumer pins a TAG
while pip records `project.version`. Nothing in the run path reads
`__version__` — which is exactly why a stale one survives a green suite,
and why a consumer installing at a pre-release tag can end up with a
package that reports the previous release. This is the only machine check
on that; the tag name itself remains a human step.
"""
tomllib = pytest.importorskip("tomllib")
pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8"))
assert llm_ingestion_okf.__version__ == pyproject["project"]["version"]
def test_operational_tooling_stays_out_of_the_wheel() -> None:
"""`tools/` is ours, not the consumer's.
The upstream watch drives git and the coord mailbox — machinery that is
meaningful on this machine and meaningless in a consumer's site-packages.
It lives outside `src/` so it cannot ship, and this test is what makes
that a promise instead of an accident of the current build config.
"""
tomllib = pytest.importorskip("tomllib")
pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8"))
packages = pyproject["tool"]["hatch"]["build"]["targets"]["wheel"]["packages"]
assert packages == ["src/llm_ingestion_okf"]
assert (PROJECT_ROOT / "tools" / "okf_watch.py").is_file(), "the test must have a subject"