Release scope

August 7, 2026 · View on GitHub

Written before the release, per the release gate in RELEASE.md. It says what is in, what is explicitly out, and why — one reason per line, each survivable against the SemVer question a PATCH has to answer: no semantic change, no new obligation, no changed behaviour at a public interface.

No date and no cadence. 3.7.1 goes out when it can answer the release gate, not when a window opens.

In

ItemWhy it is patch-safe
Doc alignment for the harness digest and the absence rule (docs/upstream/eval-result.md, docs/IN_TOTO_PROFILE.md)Documentation only. It removes a contradiction with our own upstream submission, where the predicate already carries the optional harness DigestSet and the absence rule. No code path changes.
The CI work from PR #134 (pyproject.toml: pin the ruff rule set, cap <0.17, mypy<3)Build tooling only, not shipped behaviour. Merged 2026-08-07 as 6a3011f, 22/22 checks green. The measurement that justifies it is recorded in pyproject.toml itself: on the identical tree, ruff 0.15.x applies 59 default rules and exits 0 over all 258 tracked .py, ruff 0.16.x applies 413 and reports 1168 findings.
The version-consistency gate (scripts/check_version_and_changelog.py extension + tests)A check, not a shipped code path. Nothing in src/ changes. Its first job is to verify its own release.
The release gate section in RELEASE.md and this scope fileProcess documentation.
The post-tag drift fix (b48e52b): anchor check 3 on the last release tagA check, not a shipped code path. It was not planned — it fell out of writing the changelog entry, because the check had stopped applying: git describe --tags returned a corpus review tag, _semver_tuple read it as (0, 0, 0), and every real version compared as bumped past it. One non-trivial commit had been sitting undelivered since v3.7.0 under that blind spot.
The invariant tests for the two in-toto docs (2c5e7a5)Tests only. Aligning the docs fixed the instance; nothing kept them aligned, which is how they drifted apart in the first place.
The asymmetry non-claim in both in-toto copies (b6f9395)Documentation only. The submitted spec gained a third ## Non-claims paragraph on 2026-08-07 (35c83da); both copies described a predicate that claimed more than the one actually submitted. Measured: the other five upstream changes were already carried by 871453c.
Check 6 of the version gate + the truth list (768e299, docs/version_truth_list.md)A check and a document, not a shipped code path. Check 6 finds places that claim a current version without being declared — its first finding was the truth list itself.
SUPPORT.md and COMPATIBILITY.mdNew documentation, no obligation added. Both write down what already holds: SUPPORT.md repeats SECURITY.md's supported-version sentence rather than softening it, COMPATIBILITY.md spells out what the existing SemVer commitment already implies.
docs/openssf_best_practices_self_assessment.mdDocumentation. States the measured Scorecard value (6.5/10, v5.5.0, 2026-08-07) and the honest per-criterion state. No application filed.

Two of these five were not in the first version of this list. That is the point of writing a scope list down rather than remembering it: on 2026-08-07 at 19:19 the list said four items while the branch carried seven commits, and the two missing ones were the two that had been found rather than planned. A list that does not contain what actually ships is the thing it was built against.

Out, and why

ItemWhy not in 3.7.1
ResourceDescriptor for harness/suite, the profile matrix, the exact score as its own profileAll three touch field semantics. That is at least a MINOR, and each deserves its own upstream discussion after in-toto PR 575 lands.
A second independent validator implementationNew surface, not a fix.
The conformance corpus as its own repositoryRepository-level change with its own release and licence questions.
K2 and K3 acceptance criteriaArchitecture work with executable criteria still to be written; nothing to ship yet.
stash@{0}targetSubjectDigest in the per-edge result entryMeasured, not assumed. It is out. See below.
stash@{1}if False: in evalclaim.pyA planted defect from an adversarial probe. It disables the check that samples.n matches the claim's n. Never ships, and deliberately has no safety branch: a branch whose only content is the removal of a check is worse than no branch.

The stash question, answered by measurement

The audit asked it because one stash touches src/proofbundle/relation.py, and the honest answer decides whether it may ride along in a PATCH. Measured on 2026-08-07 against main at cf39e9f:

stash@{0} applies cleanly (git apply --check, rc 0) — and that is exactly what makes it a problem. It adds a targetSubjectDigest key to the entry dict built in verify_relationship_edges. main already validates and cross-checks targetSubjectDigest elsewhere (declaration validation, resolution against the attached target, the fail-closed codes from PB-2026-0717-01), but it does not surface the field in the per-edge result. So this is not a fix for something broken; it is new output.

And that output is not internal: relation_statement.py:260 puts the result of verify_relationship_edges into r["lineage"] of a relation statement — a structure that gets signed. A new key changes emitted bytes. New behaviour at a public interface is a MINOR, not a PATCH. It stays out of 3.7.1, preserved on safety/stash-relation-targetsubjectdigest-20260807, and belongs in the same discussion as the rest of the relation/v0.1 surface.

stash@{2} is test-only and does apply. It adds test_no_secret_value_ever_reaches_output to tests/test_fork_pr_secret_isolation.py: a reachability proof that the fork-PR guard reports secret names (public YAML identifiers) but can never emit a secret value — the triage for a CodeQL clear-text-logging finding. Measured: applies to main, suite goes 34 → 35 tests, all green. No src/ change, no semantics. It is patch-safe and may ride along; it is not required for the release. Preserved on safety/stash-forkpr-secret-value-test-20260807.

External surfaces to pull after the release

SurfaceWhat has to followWho
PyPIfollows automatically from the release workflow (build once, attest, digest-gated upload)release workflow
README badgelive shields.io badges — nothing to edit. Measured: README hard-codes no version string, so it cannot go stalenobody, by design
b7n0de.com/proofbundlethe version number and the "checked on" line; both string tables (EN and DE) — the gate compares every PyPI latest <code>X.Y.Z</code> occurrence, so one translated string left behind is a findingOwner (the page is an outward surface and needs its own GO)
Description of in-toto PR #575stated 3.6.2; corrected to 3.7.0 on 2026-08-07 under QITEM-PB-AUDIT-P0-01. Must be pulled again on every release while the PR is openwhoever releases
CITATION.cff, RELEASE.md, docs/readiness_pack/PROGRESS.mdin-repo, enforced by the gate — listed here so the list is complete, not because they need a humanthe gate

What the gate does not touch, deliberately

Historical statements stay as they are: since v3.7.0 in INTEGRATIONS.md, as of v3.7.0 in CROSS_IMPLEMENTATION_REPORT.md and the two docs/readiness_pack/ files, every older CHANGELOG.md heading, and everything under audit_artifacts/370/. They record when something became true. Bumping them would turn a fact into a false claim, which is a worse failure than the drift the gate exists to catch.