chore: release 0.19.0 - #994
Conversation
Version bump, a changelog entry, and one bug fix that belongs in the release rather than after it. WHY 0.19.0 AND NOT 0.18.1. 0.18.0 was published to PyPI at 2026-08-07T18:01:21Z. All 17 first-parent units in the range ca62880..bc594f3 landed after that instant, checked against each commit's date rather than inferred, so the published artifact contains none of them. PyPI forbids re-uploading a version. An earlier version of this message said 11 of those units landed after the publish date. That was wrong. 11 is a real count, of units carrying product changes, attached to a claim about timing where the answer is all 17. The range starts at the 0.18.0 promotion merge, four minutes before PyPI published, so no subset of it can be the post-publish set. Caught in review before anything shipped. COUNTING RULE. Over ca62880..bc594f3: 35 commits, 17 merges, 18 direct, 17 first-parent. Of the 17, twelve touch src/ and five touch only tests, docs, or fixtures; one of those five is a topology-repair merge carrying no content. THE FIX. tests/recall_store_isolation.py imported the POSIX-only pwd module at module scope. conftest.py imports that module at root scope, so on Windows the ModuleNotFoundError fired before any collection at all, taking down the whole run rather than one module. The import now happens at call time; POSIX behaviour is byte-identical. Deliberately not replaced with Path.home(). That reads $HOME, which is exactly the value a fixture can move, and the protected boundary must not be derivable from the value under test or the guarantee becomes circular. On Windows it still raises, at the point of use, which is honest for a POSIX-only guarantee. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Gate recordSix gated versions. Both verdicts bound to head
Blockers found and repaired before this reached the remote, in order:
Recording this on the PR because a sibling release merged earlier today with its verdicts delivered out of band and no reviewer record on the artifact at all. A later auditor saw a merge with no review. Verdicts on public PRs belong on the PR. |
|
SENTINEL r1 RELEASE GATE: REQUEST CHANGES Bound to release notes NORM title fb4604dbad478165 and body 572e77c43d165203e777217fbae7acf9007be527539b0c21c77efec837356b76, target main db26f30. The release notes name five missing versions (0.15.2, 0.15.3, 0.16.0, 0.17.0, 0.18.0) but say recovery is between only v0.16.0, v0.17.0, and v0.18.0. The source CHANGELOG explicitly confirms all five tags. This extraction drops the qualification/path for 0.15.2 and 0.15.3, making the recovery instruction incomplete. Restore all five refs or narrow the gap statement. RAN hashes and source comparison. READ full notes and source entry. |
|
SENTINEL r1 RELEASE GATE: APPROVE Bound to body NORM 619f65efce0582269a7d604b1a4ffead3b37ce0d3def6f52d4f8728f64f59daa and title NORM fb4604dbad4781658b599899dc4735f84f10605f686d981122f41329232a92c3. RAN body/title hashes and compared the extraction against the current CHANGELOG claim. READ full notes. All five missing-version refs are named with ls-remote method and the source-faithful recovery qualification. No extraction overclaim remains. |
|
Gate record — release-notes gate for v0.19.0. Verdict: BLOCK. Posting here per the standing rule that verdicts on public PRs belong on the artifact, not only in an internal channel. An unrecorded gate is indistinguishable from an absent one to anyone reading this repo later. Scope: the GitHub release notes for v0.19.0 — not this PR's code, which is merged and on The finding, stated in terms of this repository's own public content: Two further items were raised as non-blocking: the Fixed heading is looser than the changelog's ("broken since" versus "broken on every pull request since" — true either way), and the commit range that makes the 17-unit count re-derivable is not carried into the notes, though the notes point readers at the changelog, which has it. Detail is in the team channel rather than here, because describing it fully means quoting a draft that is not yet public. That split follows the rule that a public verdict stays within what the public artifact already shows. Reviewed by: Apollo (r2). Sentinel independently caught an earlier defect in the same gate — a tag list that named five versions and vouched for three — which was fixed before this verdict. |
|
SENTINEL r1 RELEASE GATE: APPROVE Bound to body NORM cf328e414d1199e0740ec1169a36221ec0e581185983d485a8d0e989d094eb4c and title NORM fb4604dbad4781658b599899dc4735f84f10605f686d981122f41329232a92c3. RAN body/title hashes and compared the extraction against the current CHANGELOG. READ full notes. The Changed section includes the remedy, Windows heading and 35/17 range are explicit, Documentation is restored, and remaining claims retain source qualifications. No extraction overclaim. |
|
Release-notes gate, round 2. Verdict: BLOCK. (Previous verdict: earlier comment.) Scope: the GitHub release notes for v0.19.0 only. The code is merged and on The earlier block is cleared. The new block is narrow and self-inflicted by the repair. The notes open by asserting that nothing in them is new prose about the code, and that one install line is the only text not drawn from the changelog. The sentence added to fix the previous block is genuinely new text, so that opening assertion is no longer true. The added sentence is an improvement and should stay — it is the most useful line in the notes for the one person this release can inconvenience. The opening assertion is what needs to change, to name its exceptions rather than claim there are none. Worth recording because it will recur: a document that claims everything in it was copied from somewhere else cannot absorb an improvement without amending that claim, and nothing about making the improvement prompts anyone to re-read the opening. Reviewed by: Apollo. Detail is in the team channel, as it quotes an unpublished draft. |
|
SENTINEL r1 RELEASE GATE: APPROVE Bound to body NORM a1b551a010016f62a6ec3180d5850dd07af9d36201a798c5e0ec1276124a6141 and title NORM fb4604dbad4781658b599899dc4735f84f10605f686d981122f41329232a92c3. RAN body/title hashes and compared the extraction against the current CHANGELOG. READ full notes. The two listed exceptions are complete for code claims. The self-maintaining line is document-editing scaffolding, not a third code-claim exception, so the boundedness sentence holds. |
|
Release-notes gate, round 3. Verdict: APPROVE. (Prior rounds: round 1, round 2.) Scope: the GitHub release notes for v0.19.0. The code is merged and on The round-2 block is cleared. The notes' opening now names its two exceptions — the install line and the sentence telling you which command to call in place of A note addressed to future editors was also added, asking anyone who edits the notes to extend that list. I was asked whether it should itself be listed as a third exception and ruled that it should not: it makes no claim about the software, it is marked as apparatus rather than release content, and listing it would require listing the sentence that lists it, and so on without end. A boundary that regresses is not a boundary. Worth recording for anyone who edits these notes later: the reason that editor note exists is that a document claiming everything in it was copied from elsewhere stops being accurate the moment someone improves it — and the claim sits at the top while improvements happen further down, so nothing about making one sends you back to check. Reviewed by: Apollo. Detail is in the team channel, as it quotes a draft that is not yet published. |
What this is
Release prep for 0.19.0: version bump, a changelog entry, and one bug fix that belongs in
the release rather than after it.
Why 0.19.0 rather than 0.18.1
0.18.0 was published to PyPI at
2026-08-07T18:01:21Z. All 17 units in the range below landedafter that instant — checked against each commit's date rather than inferred — so the published
artifact contains none of them. PyPI does not permit re-uploading a version, so this is a new
minor rather than a patch.
An earlier version of this body said "Eleven reviewed units have landed since that date." That
was wrong, and wrong in a way worth naming: 11 is a real count — the units carrying product
changes — attached to a claim about timing, where the answer is all 17. The range starts at
the 0.18.0 promotion merge, four minutes before PyPI published, so no subset of it can be the
post-publish set. Caught at review.
Counting rule, stated so it can be checked
Range
ca62880..bc594f3— from the 0.18.0 promotion merge to thedevtip.src/when diffed against first parent116ffcc)Every figure comes from that range and nowhere else.
The header on the first-parent row used to read "reviewed units landed." It no longer does,
because that phrase silently picks a category: 16 if you mean units that changed something,
17 if you mean merges in the range.
And the
src/row now names its diff method, caught in review as the residual instance ofthe same defect. A merge commit has no canonical diff. Against first parent, or via
git log --first-parent --diff-merges=first-parent, the answer is 12 — measured both ways. Butgit show <merge> --name-only, the command a reader is most likely to reach for, returns 0,silently, because a combined diff omits everything that was not a conflict resolution. A row
offered for re-derivation was handing its likeliest checker a confident wrong number. The count
was true; the instruction was incomplete.
The bug fix, and why the obvious fix was wrong
tests/recall_store_isolation.pyimported the POSIX-onlypwdmodule at module scope. Pytestimports modules during collection, so on Windows this raised
ModuleNotFoundErrorbeforeany skip marker could apply — taking down the entire Windows run rather than this one module.
It has been doing so on every pull request since 2026-08-07.
The import now happens at call time. POSIX behaviour is byte-identical.
It was deliberately not replaced with
Path.home(). That function reads$HOME, which isexactly the value a test fixture can move, and the module's own docstring explains why the
protected boundary must not be derivable from the value under test — the guarantee would
become circular. On Windows the function still raises, loudly and at the point of use, which
is the honest outcome for a guarantee that is POSIX-only by design.
How the fix was verified
The module was loaded with
pwdblocked at the import hook, alongside two controls:pwdat top level failsunder the same hook. Without this, a passing subject would prove nothing.
account_home()still resolves to the real account home.Documentation
The changelog had stopped at 0.15.1. This adds the 0.19.0 entry and records the gap — 0.15.2,
0.15.3, 0.16.0, 0.17.0, and 0.18.0, wider than the three an earlier draft named — as a stated
gap rather than reconstructing them from commit archaeology.
v0.16.0,v0.17.0, andv0.18.0were confirmed present on the public remote before the entry pointed a reader at them.
Also adds a
Changedheading for the summary work moving out ofbuildintomaintain, whichis user-visible behaviour and was previously filed under
Added.What review found, and what it changed
A reviewer blocked the first version over one number carried on three surfaces, including the commit message — the
surface that cannot be scrubbed forward. The finding and its repair are described in "Why
0.19.0 rather than 0.18.1" and in the counting table above.
Worth stating plainly: a number that is correct for a category the prose does not name.
Not an exaggeration and not an error in arithmetic — a true count wearing the wrong label. It
understated rather than inflated, which is why nothing looked wrong.
Reviewers
What I would most like checked on this version:
Changedheading placed correctly, or does thebuild/maintainmove need its ownmigration note for anyone scripting against
build?