`uv sync --frozen` resolved ruff 0.15.22 and the tree read clean. A loose install resolves 0.16.6, under which the SAME untouched code reports 148 findings -- 4 more than round 9 counted, because this round added four files. All of them are new rules rather than new defects: 0.16 widened the default rule set to whole families (YTT, ASYNC, PL, ISC, C4, UP, B, SIM, FURB, ...). (`[skip-docs]` is for CLAUDE.md, which a lint-configuration change does not reach. README's developer section IS updated in this commit.) THE DEFECT IS NOT THE 148, IT IS THAT NOBODY CHOSE THEM. `[tool.ruff]` set only `line-length` and `target-version`, so the acceptance was ruff's default, and the tree stayed green only as long as the lockfile froze an old ruff. `select` is now written down: `E4`, `E7`, `E9`, `F` (the historical default), `I` because this tree already keeps imports sorted, and `RUF100` so a `noqa` that has stopped meaning anything is caught rather than left as decoration. Pin `ruff>=0.9` -> `ruff>=0.16.6,<0.17`. Per rule, before -> after: RUF100 50 -> 0, I001 20 -> 0, ISC004 19, PLW1510 8, C408 8, EXE001 6, RUF007 5, PLE2515 4, UP031 3, B017 3, and fourteen more with 2 or fewer -- the families out of the declared set are 0 by selection, and 148 is the number to start from if they are adopted, which is a separate decision and not one to take inside a version-pin commit. 57 were auto-fixed; one E402 was reintroduced by the import-sorting fix merging a block away from its `noqa`, and got the directive back rather than a bare one. `S` IS MEASURED OUT, NOT ASSUMED OUT: it reports 2657 `S101` on a suite whose every assertion is an `assert`, and `S603` flags 19 subprocess calls of which one was ever marked -- selecting it buys 18 suppressions and no defect. Two `noqa` directives naming non-selected rules were dropped with that reason recorded in the configuration instead. THE TWO FILES 0.16 WOULD REFORMAT ARE MARKDOWN, NOT PYTHON: `README.md` and `docs/2026-09-08-blindsone-below-k-k2.md`. 0.16 formats fenced Python inside markdown, and both blocks are RECORDS -- the second is a quotation of `COST_VOCABULARY` as it stood when that measurement was taken. Reformatting a quotation makes it stop being one, so markdown is excluded from the formatter and `ruff format --check .` stays in the acceptance over `.py`. `tools/okf_consume_measure.py` is fenced by the order as run-not-edited, so its three findings are exempted by path with the reason and the debt named, and its bytes are untouched. THE LOCKFILE TRAP IS CLOSED, NOT AVOIDED. `uv.lock` predated the `[ocr]` extra, so any unlocked resolve wrote that extra's transitive tree back into it -- 681 insertions over 4 deletions, twice now, and round 9 recorded the cause as `uv run` OUTSIDE the project when it is `uv run` without `--frozen` INSIDE it. The relock is complete for every declared extra (703 insertions, 26 deletions), and measured after it, an unfrozen `uv run` leaves the file alone. `ruff check src tests tools`, `ruff format --check .` (0.16.6), `mypy src` over 21 files and 1535 tests, all green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
127 lines
4.8 KiB
Python
127 lines
4.8 KiB
Python
"""Door C's own outcome is a bundle the reading direction can open.
|
|
|
|
vegnormal-okf, 2026-09-08 (FUNN 1): `import_bundle` wrote the root index with
|
|
no frontmatter and took no `root_frontmatter_values`, so it could not declare
|
|
`bundle_id`. `okf consume` then refused the result with exit 1,
|
|
`bundle_id_missing` -- section 3.1's identity tuple is `(bundle_id,
|
|
concept_id)` and half of it was absent. The consumer's workaround was to use
|
|
Door C as a GATE and write the consumable tree themselves.
|
|
|
|
The fix is the mechanism Door B already has and Door C did not: a profile
|
|
names a key, the CALLER owns its value (decision E1). It is keyword-only with
|
|
a default of `None`, so every existing call site emits the bytes it always did
|
|
-- a consumer with branch bases built through this door is not asked to
|
|
rebuild them, which is the boundary this repository states for its own
|
|
consumers.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from test_import_flow import CONCEPT, StubImportGate, place
|
|
|
|
from llm_ingestion_okf.importer import import_bundle
|
|
from llm_ingestion_okf.materialize import parse_frontmatter
|
|
from llm_ingestion_okf.profiles import DEFAULT, SEGMENTED_V1
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
TOOL = PROJECT_ROOT / "tools" / "okf_consume.py"
|
|
KNOWN_POSITIVE = PROJECT_ROOT / "examples" / "ingest-golden-segmented-okf-v0-2" / "expected-bundle"
|
|
|
|
|
|
def _consume(bundle: Path) -> subprocess.CompletedProcess[str]:
|
|
return subprocess.run(
|
|
[sys.executable, str(TOOL), str(bundle), "--question", "users"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
|
|
|
|
def test_the_known_positive_is_readable_first() -> None:
|
|
"""Before an exit 1 counts as a finding, the chain must be shown able to pass."""
|
|
assert _consume(KNOWN_POSITIVE).returncode == 0
|
|
|
|
|
|
def test_door_c_without_a_bundle_id_is_still_refused(tmp_path: Path) -> None:
|
|
"""The defect, kept as a test: silence is not the fix, a named value is."""
|
|
place(tmp_path / "source", "tables/users.md", CONCEPT)
|
|
bundle = tmp_path / "bundle"
|
|
import_bundle(
|
|
tmp_path / "source",
|
|
bundle,
|
|
"1970-01-01T00:00:00Z",
|
|
origin="external",
|
|
channel="manual",
|
|
gate=StubImportGate(),
|
|
)
|
|
assert (bundle / "index.md").is_file()
|
|
assert "bundle_id" not in parse_frontmatter(bundle / "index.md")
|
|
assert _consume(bundle).returncode == 1
|
|
|
|
|
|
def test_door_c_with_a_bundle_id_produces_a_consumable_bundle(tmp_path: Path) -> None:
|
|
place(tmp_path / "source", "tables/users.md", CONCEPT)
|
|
bundle = tmp_path / "bundle"
|
|
import_bundle(
|
|
tmp_path / "source",
|
|
bundle,
|
|
"1970-01-01T00:00:00Z",
|
|
origin="external",
|
|
channel="manual",
|
|
gate=StubImportGate(),
|
|
profile=SEGMENTED_V1,
|
|
root_frontmatter_values={"bundle_id": "imported-2026-09-09"},
|
|
)
|
|
declared = parse_frontmatter(bundle / "index.md")
|
|
assert declared["bundle_id"] == "imported-2026-09-09"
|
|
done = _consume(bundle)
|
|
assert done.returncode == 0, done.stderr
|
|
payload = json.loads(done.stdout)
|
|
assert payload["bundle"]["bundle_id"] == "imported-2026-09-09"
|
|
|
|
|
|
def test_a_second_run_does_not_duplicate_the_declaration(tmp_path: Path) -> None:
|
|
"""The index is APPENDED to across runs; the frontmatter must not be."""
|
|
place(tmp_path / "source", "tables/users.md", CONCEPT)
|
|
bundle = tmp_path / "bundle"
|
|
for _ in range(2):
|
|
import_bundle(
|
|
tmp_path / "source",
|
|
bundle,
|
|
"1970-01-01T00:00:00Z",
|
|
origin="external",
|
|
channel="manual",
|
|
gate=StubImportGate(),
|
|
profile=SEGMENTED_V1,
|
|
root_frontmatter_values={"bundle_id": "imported-2026-09-09"},
|
|
)
|
|
text = (bundle / "index.md").read_text(encoding="utf-8")
|
|
assert text.count("bundle_id:") == 1
|
|
assert parse_frontmatter(bundle / "index.md")["bundle_id"] == "imported-2026-09-09"
|
|
|
|
|
|
def test_the_default_profile_names_no_root_key_and_says_so(tmp_path: Path) -> None:
|
|
"""Naming a key the profile does not carry is refused BEFORE any write."""
|
|
place(tmp_path / "source", "tables/users.md", CONCEPT)
|
|
bundle = tmp_path / "bundle"
|
|
assert DEFAULT.index.root_frontmatter == ()
|
|
try:
|
|
import_bundle(
|
|
tmp_path / "source",
|
|
bundle,
|
|
"1970-01-01T00:00:00Z",
|
|
origin="external",
|
|
channel="manual",
|
|
gate=StubImportGate(),
|
|
root_frontmatter_values={"bundle_id": "x"},
|
|
)
|
|
except Exception as exc:
|
|
assert getattr(exc, "code", "") == "index_root_frontmatter_unexpected"
|
|
else: # pragma: no cover - a pass here is the defect
|
|
raise AssertionError("an unnamed root key was written")
|
|
assert not bundle.exists(), "a refused call left a partially written bundle"
|