# R6: release v0.8.4 A patch release with one change that is not a version number: the guard pin. It carries what rounds 22 and 21 landed and no tag had -- frontmatter this library writes is YAML a YAML reader reads back the same (K3-22), and a concept's `parent:` pointer resolved all the way to the reader, with the checker at seventeen rules (K3-21) -- and it moves `[tool.uv.sources]` from guard `v1.3.0` to `v1.4.0`, because 1.3.0 refuses a flow sequence of plain scalars and this library writes them. No behaviour change in `src/` beyond the version string, no push. Tag: `v0.8.4`, local and annotated, on `69dc51f` (`chore(release): 0.8.4`). `v0.8.3` stays on `0963dfa`, `v0.8.2` on `b6c54e9`, `v0.8.1` on `3daf983` and `v0.8.0` on `4d1f9d3` -- verified with `git tag --points-at`, all four still resolve there. ## 1 What this round did, and what it did not Did: the version on the three lines it lives on (`pyproject.toml`, `src/llm_ingestion_okf/__init__.py`, and the package's entry in `uv.lock`), the guard tag in `[tool.uv.sources]`, the `[Unreleased]` block closed as `[0.8.4] — 2026-09-11` with its eight entries moved unedited plus one entry for the pin, five install lines to `@v0.8.4`, the guard-pairing prose and the pip fallback to `v0.8.4` / `v1.4.0`, a `v0.8.4` row in the tag history with `v0.8.3` demoted, the test count and its history, one commit, four gates, one tag. The block carries three headings, one each (Added 2 entries, Changed 3 + the pin, Fixed 3), so there was no duplicate heading to merge. Did not: no extractor, no arm, no rule, no flag moved. `--shell-parent`, `--follow-parent`, `--pdf-outline` and `--bold-title` stay OFF and `--title-covered` stays ON exactly as the rounds shipped them. The dependency range stays `llm-ingestion-guard>=1.2,<2.0` (section 4 says why that is a decision left open rather than a verified floor). No new dependency, PyYAML still in the `dev` group only, `[extract]` untouched, `skills/okf-consume/` and `skills/okf-consume-template/` untouched, `docs/` history not rewritten, the guard repository only read, nothing pushed. ## 2 Premises, re-measured before building on them | premise | re-measured | |---|---| | HEAD at dispatch | `e98ca6d`; `e717b1c..HEAD` is 10 commits, all K3-21, nothing else; tree clean | | `git ls-remote origin refs/heads/main` | `0308169` | | remote tags `v0.8*` | all four, `v0.8.3^{}` = `0963dfa` | | guard `v1.4.0` on Forgejo | `refs/tags/v1.4.0^{}` = `d19de8c` | | `len(contract_check.RULES)` | **17**, not 16: K3-21 added `parent_unfollowable` | | install lines: README 4, `llms.txt` 1 | confirmed, README at lines 12, 62, 77 and **570** | | `[Unreleased]` / `[0.8.3]` in `CHANGELOG.md` | lines 8 and **88**, not 42 | | `grep -rn 'v0\.7\.0\|0\.7\.0' README.md docs llms.txt CLAUDE.md` | **34 lines over 11 files**; README exactly one (the `v0.7.0` history row); `grep -rln 'v0\.7\.0' docs/` 7 before and after | | suite before the release | **1783 collected, 1782 passed, 1 skipped** (README said K3-20's 1668 / 1667 / 1) | | ruff | 0.16.6 | | coordination inbox / order queue | 0 messages at start; this order the only pending one | ## 3 The lockfile and the pin `pyproject.toml` (version and guard tag) and `__init__.py` were changed first, then `uv lock` ran: "Updated llm-ingestion-guard v1.3.0 (44e2b31a) -> v1.4.0 (d19de8cb)", "Updated llm-ingestion-okf v0.8.3 -> v0.8.4". The diff is **four lines, not the three the order expected**: the guard's `source`, the guard's `requires-dist` entry, this package's `version`, and the guard's own `version = "1.3.0"` -> `"1.4.0"`, which follows from moving the pin. No other package moved, so the file was kept as `uv lock` wrote it. In the export of the tag, `uv lock --check` exits **0**. ## 4 The dependency floor, measured and left standing The comment above `dependencies` grounds the floor 1.2 in the flow-mapping support 1.2.0 added. Run against each guard's own source (`git archive` of the tag, imported first on `sys.path`, the import path asserted): | guard | `tests/test_guard_adapter.py` | whole suite | |---|---|---| | 1.2.0 | **20 passed, 1 failed** (`test_the_guard_parses_the_flow_form_sources_our_goldens_emit`) | not run | | 1.3.0 | 21 passed | **1782 passed, 1 skipped** | | 1.4.0 (installed) | 21 passed | 1782 passed, 1 skipped | The failing test entered in `2d9fb0f` (2026-09-03) and is in every tag from `v0.6.0` on. So the tree's own suite has contradicted the floor 1.2 since before this release, and K3-21 and K3-22 require nothing 1.3.0 lacks. The floor was left as it is -- this release's order fixed the range, and moving it is a release decision of its own. It is recorded as an open question, not resolved here. ## 5 README lines the tag would otherwise make false - The two guard-pairing sentences carry two numbers each and both moved: "and `v0.8.4` points that entry at `llm-ingestion-guard` `v1.4.0`", "`v0.8.4` declares `llm-ingestion-guard>=1.2,<2.0`, which `v1.4.0` satisfies". The pip fallback installs the guard `@v1.4.0`. - The `v0.8.4` row says what the tag is, with seventeen rules, and names the pin as `v1.4.0` and the old one as "the previous pin", so the `v1.3.0` grep stays at zero. The `v0.8.3` row lost "the current tag: " and nothing else. - The test count is **1783 collected, 1782 passed, 1 skipped**. The sentence that the figure published before the `v0.8.2` release was the passed count stays: it is still true of the past, and collect still reports one more. The history parenthesis keeps every earlier figure and adds that the figure above is the `v0.8.4` release's, after K3-22 and K3-21. - `grep -n 'okf\.git@v0\.8\.3' README.md llms.txt` returns nothing (exit 1), beside the known-positive `okf\.git@v0\.8\.4` = README 4 + `llms.txt` 1. A bare `v0.8.3` remains twice, both intentional: the `v0.8.3` history row and the count history. `grep -n 'v1\.3\.0' pyproject.toml README.md llms.txt` returns nothing (exit 1), beside `v1.4.0` = `pyproject.toml` 1, `uv.lock` 2, README **4** (the order expected 3; the fourth is the new history row). ## 6 The four gates, after `git add` and after commit ruff **0.16.6**. `ruff check src tests tools` -- All checks passed. `ruff format --check .` -- 130 files already formatted. `mypy src` -- no issues in 21 source files. `pytest -q` -- **1782 passed, 1 skipped**, 1783 collected, on the release commit. `tests/test_docs_promises.py` and `tests/test_packaging.py` were run after every README and version edit (11 of 11 each time). ## 7 The acceptance gate: installation FROM THE TAG No `uv tool install`, no `uv tool uninstall`, no `--force`. The operator's `okf` on PATH (`~/.local/bin/okf`, a uv tool install) was located and not touched; everything ran from the export's own venv (CPython 3.11) under a private scratch directory, never under the hit@k instrument's shared paths. ``` git archive v0.8.4 | tar -x -C /r6-install/export cd && uv sync --frozen --extra extract ``` | row | measured | |---|---| | version from the tag's bytes | **0.8.4** (`importlib.metadata`) | | guard version from the tag's lockfile (new) | **1.4.0** | | `uv lock --check` in the export | **rc 0** | | `len(contract_check.RULES)` | **17**, the same as the working tree | | `okf check` on `skills/okf-consume/` and its payload | **conformant: 17 rules over 3 excerpts and 0 withheld entries, 0 findings**, rc 0 | | `okf project` on the five-document folder | **26 concepts of 5 documents, 52 md, 0 of 5 left out**; the folder holds 5 files before and after | | HTML corpus | **proposed 828 plan(s); 0 document(s) with no boundary; 0 unreadable**, 6 015 md | | R761 XML | **2 761 concepts** at shipped defaults, no arm flag; the folder holds 1 file at top level and 110 in total, 109 coded `extractor_unknown` | | R761 document directory | **`r761-prosesskoden/`**; denominator 1 document | | hit@1 / 8 / 50 on the R761 bundle | **6/6 / 6/6 / 6/6** at the default `k` and at `k` = 50, N = 6 scored of 8 asked | | the known-positive | **rank 1 at the default `k` and rank 1 at `k` = 50**, denominator 1 | | round 17's known-negative on the five-document bundle | the section the question names at **rank 1** (6 793 B), the neighbour at rank 2 (10 590 B); both concepts exist and both are delivered of 8 | | guard 1.4.0 against 1.3.0 on that bundle (new) | 28 frontmatter blocks in 52 md: **1.4.0 refuses 0 of 28, 1.3.0 refuses 26 of 28** (26 of 27 concept files), every refusal "a flow sequence admits flow mappings only" -- `source_offset` pairs and a `[references]` list among them | | `tests/test_guard_adapter.py` in the working tree against 1.4.0 (new) | **21 passed of 21** | The guard-1.3.0 column is the known-negative control and it is not zero, so the two columns read two different guards. The same five documents built from the working tree before the bump differ from the tag's build in exactly one line, `log.md`'s converter path (a different venv); every concept file is byte-identical. The pin's one earlier claim without a source -- 26 of 28 -- reproduces on this bundle. The three other corpus figures that came with it (2 761 of 2 763, 3 206 of 3 208, 412 of 455) were **not** measured here. The hit@k instrument lives in the consumer's repository and was only read. It writes its payloads to fixed paths another session also writes, so it ran as a scratch copy that differs from the original in exactly those two output paths (`diff`: 2 lines). The suite was not run inside the export. ## 8 Honesty limits - **One machine, one interpreter.** The installation is measured on one Intel Mac with the interpreter `uv` resolved in the export. It is not a portability claim, and the channel is a local export, not the Forgejo tag, which does not exist until the push. - **`okf project`'s 26 is ONE corpus of five documents** -- the same five every previous round used, so it is a regression control, not a sample. - **828 of 828 and 2 761 of 2 761 are ONE publisher's files from ONE product.** - **hit@1 and the known-positive rank are 6 scored questions and ONE known-positive on ONE bundle, against a fasit someone else set.** They are re-measured from the tag's bytes, which is all they add. - **The known-negative is ONE constructed question on ONE small bundle.** - **The guard row is ONE bundle with ONE guard version in each column.** It says that 1.4.0 accepts what 1.3.0 refused on this fixture, and nothing about other corpora, and nothing about Door C's `import_bundle` on an okf bundle, which is still unmeasured. - **The grep criterion is deliberately NOT "0 hits on `v0.8.3`".** Two bare occurrences remain and must. The zero on `okf.git@v0.8.3` ran beside a known-positive, so it is a measurement and not a query that could never match. - **"The tag installs" is not "the tag is correct".** No functionality is verified here beyond what K3-22 and K3-21 already measured; the rows above prove the exported bytes run and reproduce the counts the repository already published.