docs(release): R7, v0.8.5 tagged locally and measured from the tag
The release report in R6's form: premises re-measured, the one-line lockfile diff, the README lines the tag would have made false, the gates, and the acceptance gate run from a local `git archive v0.8.5` export. Two bookkeeping figures in K3-25's report corrected after re-measuring: the tests/ call denominator was 129 occurrences on 128 lines (not 112 across 13), and the outside-tests figure was 19 on 17 lines in 5 files (not 129, which was the tests/ number written into the wrong paragraph). The "exactly 1 changed result" finding is unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
64661c7198
commit
313a1497b7
2 changed files with 275 additions and 6 deletions
|
|
@ -86,9 +86,12 @@ byte-identical under both readings, section 3's gate in miniature -- and the
|
||||||
characterisation of what the line does, which is an invariant about the line.
|
characterisation of what the line does, which is an invariant about the line.
|
||||||
|
|
||||||
**One existing test changed with the code**, and it is the whole test-caller
|
**One existing test changed with the code**, and it is the whole test-caller
|
||||||
denominator: `tests/` holds **112** call occurrences of the four functions
|
denominator: `tests/` holds **129** call occurrences of the four functions
|
||||||
across **10** files, of which **13** pass the parameter explicitly. Exactly
|
on **128** lines across **10** files, of which **20** lines pass the parameter
|
||||||
**1 of 112** changed result -- the characterisation that called
|
explicitly (re-counted 2026-09-12 for the `v0.8.5` release; the figures first
|
||||||
|
published here, 112 and 13, were a line count read as an occurrence count and
|
||||||
|
a file count read as a call count). Exactly
|
||||||
|
**1 of 129** changed result -- the characterisation that called
|
||||||
`concept_scores` with no parameter because the reading it characterises used to
|
`concept_scores` with no parameter because the reading it characterises used to
|
||||||
be the default. It now names that reading; same fixture, same number. The two
|
be the default. It now names that reading; same fixture, same number. The two
|
||||||
other test files whose fixtures carry the door's form
|
other test files whose fixtures carry the door's form
|
||||||
|
|
@ -129,9 +132,11 @@ exactly what the unflagged build delivers. It does, to the byte, on every row.
|
||||||
## 5. The consumers, measured
|
## 5. The consumers, measured
|
||||||
|
|
||||||
`grep` over `build_payload(`, `concept_scores(`, `searchable_text(` and
|
`grep` over `build_payload(`, `concept_scores(`, `searchable_text(` and
|
||||||
`body_without_link_line(`, excluding `.git`, `tests/` and `.venv`: **129** hits
|
`body_without_link_line(`, excluding `.git`, `tests/` and `.venv`: **19** hits
|
||||||
in total, of which **4** fall outside `consume.py` and one of those is prose in
|
on **17** lines across **5** files (re-counted 2026-09-12 for the `v0.8.5`
|
||||||
`CLAUDE.md`. **3 call sites in 2 files**, plus the CLI's own `main` inside the
|
release; the 129 first published here is the `tests/` figure above, written
|
||||||
|
into the wrong paragraph). **8 of the 19** fall outside `consume.py`: one is
|
||||||
|
prose in `CLAUDE.md` and four are this report counting itself. **3 call sites in 2 files**, plus the CLI's own `main` inside the
|
||||||
module:
|
module:
|
||||||
|
|
||||||
| call site | what it is | passes the parameter | what the change means for it |
|
| call site | what it is | passes the parameter | what the change means for it |
|
||||||
|
|
|
||||||
264
docs/2026-09-12-r7-release-v085.md
Normal file
264
docs/2026-09-12-r7-release-v085.md
Normal file
|
|
@ -0,0 +1,264 @@
|
||||||
|
# R7: release v0.8.5
|
||||||
|
|
||||||
|
A patch release with no new functionality and one change that reaches outside
|
||||||
|
this repository: `okf.parse_frontmatter` is public API, and after K3-24 it
|
||||||
|
returns a flow STRING for a block `sources:` where it returned an EMPTY string.
|
||||||
|
The tag carries what rounds 23, 24 and 25 landed and no tag had -- K3-23's
|
||||||
|
`link_in_signal` instrument, K3-24's block-`sources` fix in all three flat
|
||||||
|
frontmatter readers, and K3-25 making the reading without the door's link line
|
||||||
|
`consume`'s default. No behaviour change in `src/` beyond the version string,
|
||||||
|
the guard pin untouched at `v1.4.0`, no push.
|
||||||
|
|
||||||
|
Tag: `v0.8.5`, local and annotated, on `64661c7` (`chore(release): 0.8.5`).
|
||||||
|
`v0.8.4` stays on `69dc51f`, `v0.8.3` 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 five 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:7`,
|
||||||
|
`src/llm_ingestion_okf/__init__.py:79`, and the package's entry in
|
||||||
|
`uv.lock:550`), `CHANGELOG.md`'s `## [Unreleased]` to
|
||||||
|
`## [0.8.5] — 2026-09-12` with the em dash copied from the `[0.8.4]` head, the
|
||||||
|
five `@v0.8.4` install lines to `@v0.8.5`, the two pairing paragraphs, the tag
|
||||||
|
history list, README's test counts and its history parenthesis, and one local
|
||||||
|
annotated tag.
|
||||||
|
|
||||||
|
Did NOT: move the guard pin, which stays at `v1.4.0` on all six tracked places;
|
||||||
|
move the dependency floor `>=1.2,<2.0`, which R6 measured and deliberately left
|
||||||
|
standing as an operator decision; add a rule, an extractor, an arm or a flag;
|
||||||
|
move `--shell-parent`, `--pdf-outline` or `--bold-title`, all three still OFF
|
||||||
|
and all three operator questions with numbers already delivered; touch
|
||||||
|
`skills/`; rewrite `docs/`; or push anything.
|
||||||
|
|
||||||
|
`link_in_signal`'s default is K3-25's delivery, not this round's. This round
|
||||||
|
releases it.
|
||||||
|
|
||||||
|
## 2 Premises, re-measured
|
||||||
|
|
||||||
|
Every premise the order carried was reproduced before anything was edited.
|
||||||
|
|
||||||
|
| premise | measured here |
|
||||||
|
|---|---|
|
||||||
|
| inbox empty | `find ~/.claude/coord/llm-ingestion-okf/inbox/ -type f \| wc -l` = 0, rc 0 |
|
||||||
|
| order queue | 0 pending, 1 claimed (this order); K3-25's order already archived |
|
||||||
|
| `git status --short` | empty |
|
||||||
|
| HEAD | `06c057f`; `git log --oneline 7faa380..HEAD` = exactly K3-25's three commits (`3816ed5`, `38320cd`, `06c057f`), nothing else |
|
||||||
|
| five tags stand | `v0.8.0` `4d1f9d3`, `v0.8.1` `3daf983`, `v0.8.2` `b6c54e9`, `v0.8.3` `0963dfa`, `v0.8.4` `69dc51f`, all `git cat-file -t` = `tag` |
|
||||||
|
| remote | `refs/heads/main` = `150c726`; all five `v0.8*` tags present, `v0.8.4^{}` = `69dc51f`. R6's tag backlog is gone, so the push list is ONE line |
|
||||||
|
| `okf check` rules | `len(contract_check.RULES)` = **17** in the work tree and **17** from the tag. K3-25 added none |
|
||||||
|
| suite | **1827 collected, 1826 passed, 1 skipped**, rc 0 (`pytest -q` and `pytest --collect-only -q`, repo root, `[extract]` installed) |
|
||||||
|
| ruff | 0.16.6, the version R4, R5 and R6 measured |
|
||||||
|
|
||||||
|
The order's line numbers had moved, as it warned: `CHANGELOG.md`'s `[0.8.4]`
|
||||||
|
head is at **103**, not 82, and README's fourth install line at **589**, not
|
||||||
|
580. Every number used here was read off this base.
|
||||||
|
|
||||||
|
The CHANGELOG's `[Unreleased]` block held **5** posts under **4** headings when
|
||||||
|
this round started -- `### Added` (K3-23), `### Changed` (K3-25), `### Fixed`
|
||||||
|
(K3-24), `### Changed` (K3-24, two posts) -- counted with
|
||||||
|
`sed -n '9,102p' CHANGELOG.md | grep -c '^- '` and `grep -n '^### '`, not read.
|
||||||
|
|
||||||
|
**Gate 1 was already closed by K3-25.** The order expected K3-23's Added post
|
||||||
|
to still end in "in a later round", a sentence the tag would falsify. It does
|
||||||
|
not: the post now says the recommendation was "carried out in the same
|
||||||
|
unreleased block below". The query that could find it is the joined one --
|
||||||
|
`tr '\n' ' ' < CHANGELOG.md | grep -c 'in a later round'` = 0 -- run beside the
|
||||||
|
known-positive `tr '\n' ' ' < CHANGELOG.md | grep -c 'recommended as'` = 1, so
|
||||||
|
the zero is a measurement. Nothing was edited.
|
||||||
|
|
||||||
|
**Gate 2 was open and one post was written.** K3-24's `### Fixed` post says the
|
||||||
|
rendering "is a READING projection, not a claim that the value is writable",
|
||||||
|
but names no cost and no denominator. One post was added under `### Changed`
|
||||||
|
carrying the measurement in section 7 below. It is the only post in the
|
||||||
|
`[0.8.5]` block this round wrote; the other five moved byte-identically,
|
||||||
|
verified by diffing the old block's non-heading lines against the new block's
|
||||||
|
(the only addition is the 13 lines of the new post; the two K3-24 `### Changed`
|
||||||
|
posts appear on both sides unchanged).
|
||||||
|
|
||||||
|
**The two `### Changed` headings were merged into one**, in the order Added,
|
||||||
|
Changed, Fixed: K3-25's post, then K3-24's two, then the new one. Each post
|
||||||
|
body moved byte-identically and no other line changed. Leaving both would also
|
||||||
|
have been legal; one was chosen because a single version block with two
|
||||||
|
identically named sections is a reader's problem, not a record.
|
||||||
|
|
||||||
|
## 3 The lockfile
|
||||||
|
|
||||||
|
`pyproject.toml` and `__init__.py` were corrected first, then `uv lock` was run
|
||||||
|
and the diff measured. **Exactly one line**, the okf version at `uv.lock:550`:
|
||||||
|
`0.8.4` -> `0.8.5`. No other package moved. The guard lines `:546` and `:578`
|
||||||
|
are untouched and still carry `v1.4.0`. `tests/test_guard_adapter.py` passed
|
||||||
|
**21 of 21** afterwards -- the check that `uv lock` did nothing to the guard it
|
||||||
|
was not asked to do.
|
||||||
|
|
||||||
|
R6's diff was four lines, three of them the pin's. This round's is one, because
|
||||||
|
the pin does not move.
|
||||||
|
|
||||||
|
## 4 README lines the tag would otherwise make false
|
||||||
|
|
||||||
|
- The **five install lines** (`README.md:12`, `:62`, `:77`, `:589`,
|
||||||
|
`llms.txt:9`), measured on this base, not quoted from the order.
|
||||||
|
- The **two pairing paragraphs**. `README.md:66-67` and `:80-81` each had ONE
|
||||||
|
number to correct this round, not two: the okf tag. The guard tag `v1.4.0`
|
||||||
|
stays in both, and `README.md:76` -- the pip fallback that installs the guard
|
||||||
|
-- was not touched at all.
|
||||||
|
- The **tag history list**: a `v0.8.5` row as "the current tag", written from
|
||||||
|
this round's own CHANGELOG wording and carrying **seventeen** rules as
|
||||||
|
measured here, not copied from the row above; `v0.8.4` demoted from "the
|
||||||
|
current tag" to past by striking those three words and nothing else;
|
||||||
|
`v0.8.3`, `v0.8.2`, `v0.8.1`, `v0.8.0` and `v0.7.0` untouched. The row makes
|
||||||
|
no claim about the guard pin, so README's `v1.4.0` count stays at 4.
|
||||||
|
- The **test counts** (`:950-952`): 1783/1782/1 of 2026-09-11 to
|
||||||
|
**1827/1826/1** of 2026-09-12, both measured here.
|
||||||
|
- The sentence that follows them -- "the figure published before the `v0.8.2`
|
||||||
|
release was the PASSED count, and `pytest --collect-only -q` reported one
|
||||||
|
more" -- was **left standing**, because it is still true on this round's
|
||||||
|
numbers: 1827 is exactly one more than 1826, and the one is the skip.
|
||||||
|
- The **history parenthesis**: 1783 becomes a past leg ("through the `v0.8.4`
|
||||||
|
release, after K3-22 and K3-21") and the current figure becomes the `v0.8.5`
|
||||||
|
release's, after K3-23, K3-24 and K3-25. Changing only the date would have
|
||||||
|
made the previously published figure disappear rather than become history.
|
||||||
|
|
||||||
|
`tests/test_docs_promises.py` (**5 of 5**) and `tests/test_packaging.py`
|
||||||
|
(**6 of 6**) were run after the README and version edits, both green.
|
||||||
|
|
||||||
|
## 5 Two bookkeeping figures in K3-25's report
|
||||||
|
|
||||||
|
Both were re-measured rather than taken from the order, and both were wrong in
|
||||||
|
the published file.
|
||||||
|
|
||||||
|
- Paragraph 2 said `tests/` holds **112** call occurrences of the four
|
||||||
|
functions across 10 files, of which **13** pass the parameter. Measured:
|
||||||
|
**129** occurrences on **128** lines across **10** files, with **20** lines
|
||||||
|
passing `link_in_signal=`. The substantive finding -- exactly **1** changed
|
||||||
|
result -- stands, and `1 of 112` became `1 of 129`.
|
||||||
|
- Paragraph 5 said **129** hits outside `tests/`. Measured: **19** occurrences
|
||||||
|
on **17** lines across **5** files. The 129 is the `tests/` figure written
|
||||||
|
into the wrong paragraph. Of the 19, **8** fall outside `consume.py`: one is
|
||||||
|
prose in `CLAUDE.md` and four are that report counting itself.
|
||||||
|
|
||||||
|
Both corrections name what the wrong number actually was, so a reader meeting
|
||||||
|
the old figure elsewhere can place it.
|
||||||
|
|
||||||
|
## 6 The gates
|
||||||
|
|
||||||
|
Run after `git add` and after the commit, never before:
|
||||||
|
|
||||||
|
| gate | result |
|
||||||
|
|---|---|
|
||||||
|
| `ruff check src tests tools` | All checks passed (ruff **0.16.6**) |
|
||||||
|
| `ruff format --check .` | 132 files already formatted |
|
||||||
|
| `mypy src` | Success: no issues found in 21 source files |
|
||||||
|
| `pytest -q` | **1826 passed, 1 skipped**, rc 0 |
|
||||||
|
|
||||||
|
Grep criteria, each with a control:
|
||||||
|
|
||||||
|
| query | result |
|
||||||
|
|---|---|
|
||||||
|
| `grep -n 'okf\.git@v0\.8\.4' README.md llms.txt` | 0 hits, rc 1 |
|
||||||
|
| `grep -c 'okf\.git@v0\.8\.5' …` | README **4**, `llms.txt` **1** = 5 -- the known-positive that makes the zero above a measurement |
|
||||||
|
| `grep -n 'v0\.8\.4' README.md llms.txt` | **2**, both named: `README.md:102` the tag-history row, `README.md:959` the history parenthesis. Not 0, and not to be made 0 |
|
||||||
|
| `grep -n 'v1\.4\.0' pyproject.toml uv.lock README.md` | `pyproject` **1**, `uv.lock` **2**, README **4** -- unmoved, which is what says the pin was not touched |
|
||||||
|
| `grep -n 'v1\.3\.0' pyproject.toml README.md llms.txt` | 0 hits, rc 1 |
|
||||||
|
| `grep -rn 'v0\.7\.0\|0\.7\.0' README.md docs llms.txt CLAUDE.md \| wc -l` | **35** lines over **8** `docs/` files -- unchanged. README's one hit is the `v0.7.0` tag-history row and stays |
|
||||||
|
|
||||||
|
## 7 The acceptance gate: installation FROM THE TAG
|
||||||
|
|
||||||
|
Local export only. `git archive v0.8.5 | tar -x` into
|
||||||
|
`/private/tmp/okf-r7-scratch/r7-install/export`, then
|
||||||
|
`uv sync --frozen --extra extract` (plain `--frozen` drops `[extract]` and
|
||||||
|
`mypy src` falls on pdfplumber). No `uv tool install`, no `--force`, no
|
||||||
|
uninstall: the operator's own `okf` at `/Users/ktg/.local/bin/okf` was read and
|
||||||
|
left alone. Everything below ran from `<export>/.venv/bin/`.
|
||||||
|
|
||||||
|
| row | denominator | result |
|
||||||
|
|---|---|---|
|
||||||
|
| version | 1 | `importlib.metadata.version('llm-ingestion-okf')` = **0.8.5** |
|
||||||
|
| guard version | 1 | `llm-ingestion-guard` = **1.4.0**, unmoved |
|
||||||
|
| `uv lock --check` | 1 | rc **0**, captured directly |
|
||||||
|
| `contract_check.RULES` | 1 | **17**, equal to the work tree's |
|
||||||
|
| `okf check` on the shipped skill | 1 | rc 0, `conformant: 17 rules over 3 excerpts and 0 withheld entries, 0 findings` |
|
||||||
|
| `okf project` on the five-document folder | 5 documents | **26** concepts, **52** md files, **0 of 5** left out -- R6's numbers to the unit |
|
||||||
|
| HTML corpus | 828 documents | `proposed 828 plan(s); 0 document(s) with no boundary; 0 unreadable`, **6 015** md |
|
||||||
|
| R761 XML | 110 source files, 1 at top level | **2 761** concepts over 2 737 directories, of which `11` and `12` hold two each; document directory is `r761-prosesskoden/`, not the UUID |
|
||||||
|
| hit@1 / @8 / @50 on R761 | **N = 6** scored of 8 asked | **6/6 · 6/6 · 6/6** |
|
||||||
|
| known-positive rank | 1 | rank **1** at the default `k` and rank **1** at `k` 50 |
|
||||||
|
| known-negative (K3-17) | 1 question | rank 1 = the RITB section (**6 793 B**), rank 2 = «Prøvedrift» (**10 590 B**); both concepts present and delivered |
|
||||||
|
| block `sources:` read to 0 empty | 4 605 files | see below |
|
||||||
|
| the flow string through PyYAML | 4 605 files | see below |
|
||||||
|
|
||||||
|
**The hit@1 row matters more this round than last**, because K3-25 makes
|
||||||
|
`link_in_signal=False` the default and that is a ranking change on a published
|
||||||
|
payload form. K3-23's claim was that none of the five shipped bundles carries
|
||||||
|
the door's link line, so the row should not move. It did not: every S1-S6 row
|
||||||
|
is rank 1, the known-positive is rank 1 at both `k`, and S1's `spent` is
|
||||||
|
**31 031** -- the value STATE records for the default reading.
|
||||||
|
|
||||||
|
**The four bundles, read from the tag's bytes.** Source directory, named
|
||||||
|
because it is not named in K3-24's report:
|
||||||
|
`/Users/ktg/repos/vegnormal-okf/build/ferdig/`. Chosen after verifying its
|
||||||
|
denominators against K3-24's table first: files carrying a frontmatter block
|
||||||
|
are **2 757 / 447 / 1 134 / 271** for `r761-2025`, `n100-2023`, `n200-2024`,
|
||||||
|
`n500-2024`, exactly K3-24's. Of those, the ones carrying a BLOCK `sources:`
|
||||||
|
are **2 756 / 446 / 1 133 / 270** = **4 605**. All three flat readers
|
||||||
|
(`materialize.parse_frontmatter`, `structure._split_frontmatter`,
|
||||||
|
`profiles._split_frontmatter`) return a non-empty value on **0 empty of each**,
|
||||||
|
reading nothing but the bundles.
|
||||||
|
|
||||||
|
**The known-positive control for that zero.** The same read with `v0.8.4`'s
|
||||||
|
flat reader (`git archive v0.8.4 src/llm_ingestion_okf` into scratch,
|
||||||
|
`sys.path.insert`) returns EMPTY on **2 756 / 446 / 1 133 / 270** -- 4 605 of
|
||||||
|
4 605, K3-24's before-numbers to the file. The instrument can find, so the zero
|
||||||
|
is a measurement.
|
||||||
|
|
||||||
|
**The reservation, measured and not asserted.** The string
|
||||||
|
`parse_frontmatter` now returns for a block `sources:` was passed to
|
||||||
|
`yaml.safe_load` on each of the same 4 605 files. It is read back on **0 of
|
||||||
|
4 605**. The reason is visible in one value:
|
||||||
|
|
||||||
|
```
|
||||||
|
[{ resource: https://…/api/nisosts/859990?languageCode=nb, title: N500:2024 }]
|
||||||
|
```
|
||||||
|
|
||||||
|
The `?` opening the query string ends the flow scalar, and PyYAML raises
|
||||||
|
`ParserError while parsing a flow mapping`. So the fix is an improvement for a
|
||||||
|
consumer who read the empty value and concluded the address was absent, and a
|
||||||
|
REGRESSION for a consumer who passed the return value straight to a YAML
|
||||||
|
reader: they now get a parse error where they got something empty that parsed.
|
||||||
|
The emitter `materialize._render_sources` still writes flow, so no bundle bytes
|
||||||
|
move. PyYAML 6.0.3 is a dev dependency and the export carries it; this row was
|
||||||
|
measured with the export's interpreter, and reproduced identically with the
|
||||||
|
work tree's.
|
||||||
|
|
||||||
|
## 8 Honesty limits
|
||||||
|
|
||||||
|
- **One machine, one interpreter, a LOCAL export.** The installation is
|
||||||
|
measured on one Intel Mac from `git archive v0.8.5`, not from the Forgejo
|
||||||
|
tag, which does not exist until the operator pushes. It is not a portability
|
||||||
|
claim and not a claim that the channel works.
|
||||||
|
- **`okf project`'s 26 is ONE corpus of five documents** -- 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.**
|
||||||
|
- **The known-negative is ONE constructed question on ONE small bundle.**
|
||||||
|
- **The four bundle rows are ONE producer's four bundles from ONE generator.**
|
||||||
|
"0 empty" says nothing about a bundle someone else built, and the directory
|
||||||
|
they were read from is named above because K3-24's report does not name it:
|
||||||
|
the denominators match K3-24's table, which is the evidence it is the same
|
||||||
|
material, not a certificate that it is the same directory.
|
||||||
|
- **The grep criterion is deliberately NOT "0 hits on `v0.8.4`".** Two
|
||||||
|
occurrences remain and must. The zero on `okf.git@v0.8.4` ran beside a
|
||||||
|
known-positive that returned 5, so it is a measurement and not a query that
|
||||||
|
could never match.
|
||||||
|
- **`okf.parse_frontmatter` CHANGES PUBLIC READ BEHAVIOUR.** A consumer who
|
||||||
|
passed its return value for `sources` to a YAML reader and got something
|
||||||
|
empty that parsed now gets a parse error: PyYAML reads the returned string
|
||||||
|
back on **0 of 4 605** block files. That is a regression for them even though
|
||||||
|
it is a fix for everyone who read the empty value as an absent address. It is
|
||||||
|
stated here, in the CHANGELOG and in the tag-history row, because a release
|
||||||
|
that sells a read fix without saying who it costs lies by omission.
|
||||||
|
- **"The tag installs" is not "the tag is correct".** No functionality is
|
||||||
|
verified here beyond what K3-23, K3-24 and K3-25 already measured; the rows
|
||||||
|
above prove the exported bytes run and reproduce the counts the repository
|
||||||
|
already published.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue