Skip to content

chore(deps): bump deps past semver-major and pin author digests - #1223

Merged
dekobon merged 5 commits into
mainfrom
chore/dep-upgrades
Aug 6, 2026
Merged

chore(deps): bump deps past semver-major and pin author digests#1223
dekobon merged 5 commits into
mainfrom
chore/dep-upgrades

Conversation

@dekobon

@dekobon dekobon commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Advances the dependency graph past the semver-major line Dependabot is
configured to ignore, refreshes every lockfile, and closes a test gap
the review of that work turned up.

make pre-commit passes: 5163 Rust tests (5161 on main, plus
exactly the two new pins) and 363 passed / 1 xfailed on the Python
side. All 26 complexity-class probes stay within bounds.

Dependencies

Tier Change
Lockfiles 125 packages in the root workspace, 13–18 in each of the six excluded crates
semver-major gix 0.83 → 0.86, sha2 0.10.9 → 0.11.0, hmac 0.12.1 → 0.13.0, num-derive 0.4 → 0.5, clap_mangen 0.2 → 0.3, jsonschema 0.46 → 0.49 (dev)
Pinned-by-policy pyo3 0.29.0 → 0.29.2 (+ pyo3-build-config) — a patch inside the minor the manifest comment guards
Python uv lock --upgrade + regenerated hash-pinned exports: mypy 2.1 → 2.3, pyright 1.1.409 → 1.1.411, pytest 9.0.3 → 9.1.1, maturin 1.13.3 → 1.14.1

Grammars are untouched. All twenty external grammar crates and the
tree-sitter runtime are already at their latest published versions,
so none of the usual snapshot churn applies.

The whole major-bump set cost three source lines: one import (hmac
0.13 splits KeyInit out of Mac) and two mypy 2.3 tightenings in
test annotations.

No public-API change. No gix or RustCrypto type appears in a
public signature, so STABILITY.md is unaffected.

Two manifest comments were stale and are corrected. The sha2 pin
claimed to match a version "locked transitively via grammar crates";
cargo tree shows the root crate is now its only dependent. The hmac
comment claimed digest 0.10 added no new trait version, when
actix-http had already brought digest 0.11 into the graph via
sha1 0.11 — which is the island sha2 and hmac now join.

Test gap closed

Reviewing the sha2 / hmac bump surfaced something worth fixing on
its own. Every assertion on AuthorId::hashed and
AuthorHashKey::apply was relational — it compared one digest
against another produced by the same build, so it held whatever the
hash library emitted. A repo-wide search found no 64-hex literal
anywhere.

That is the wrong shape for these two, because their output is a
stored value with cross-version contracts on both sides.
src/vcs/cache.rs writes unkeyed digests to disk and honours them
across version boundaries (CACHE_SCHEMA_VERSION tracks the on-disk
format, not the hash implementation, so a dependency bump does not
invalidate an existing cache), and AuthorId::hashed documents the
emitted digests as stable cross-report pseudonyms.

Expected values are derived from Python's hashlib / hmac, so the
new tests assert conformance to SHA-256 and RFC 2104 rather than
agreement with our own implementation.

Verified by perturbation, per .claude/rules/testing.md:

Perturbation Failures across the lib suite
SHA-256 pre-image changed 2 — both new pins, nothing else
HMAC pre-image changed 1 — the keyed pin, nothing else

That second column is the finding, measured rather than argued: no
pre-existing assertion noticed a changed hash output. The digests did
not in fact move here — SHA-256 is SHA-256 — but nothing in the suite
could have told us.

Performance

Measured by interleaved paired A/B per
docs/development/benchmarking.md#interleaved-ab, since the host was
at load 6–8 throughout. Corpus slice: 177 files, 903 KiB, 14 languages.

No detectable change. A 7-round sweep left corpus/parse/tree-sitter
slower in 6 of 7 rounds, which had a mechanism worth chasing — parsing
is pure grammar C and cc moved 1.2.62 → 1.4.0, recompiling every
grammar. It did not replicate: at 15 rounds with corpus/walk/nom as a
control, parse was 10/15 slower with a 1.3% median (chance), and the
control's spread (0.84–1.27) was wider than the subject's entire
range (0.95–1.08). The measurement floor on this host exceeds any
effect present.

If you run a single cargo bench, criterion will print a
Performance has regressed line against its stored baseline. That is
the sequential-comparison artifact the benchmarking doc warns about —
two runs minutes apart on a loaded host. The paired result above is the
one to trust.

Deliberately not included

  • ruff stays capped at <0.16. ruff 0.16.0 expanded the default
    rule set from 59 to 413 rules; because the config selects with
    extend-select, the effective set jumps 265 → 501 on identical
    config, pulling in 28 families including PL — which the comment
    directly above extend-select says is deliberately omitted. The fix
    is a one-line config change (extend-selectselect, verified to
    give 268 rules and a clean ruff check under 0.16.1), but it is a
    separate decision. Filed as deps(py): adopt ruff 0.16 by pinning the rule set with select #1222.
  • clap_mangen 0.3 reorders the SYNOPSIS, moving the required
    <-t|--type> after the optional flags in man/bca-count.1 and
    man/bca-find.1. Two lines; kept deliberately.

Addendum: CI dispatch trigger

Reviewing this PR's Codecov report turned up an unrelated problem worth
fixing while it is visible.

Codecov compares a PR against the most recent ancestor that carries a
report
. Main's head d818e306 has zero check-runs and therefore no
coverage upload, so this PR is baselined against f71bcc7d, eight
commits behind. The +64 lines / +66 hits / -2 misses in the Codecov
comment are almost entirely those eight commits — two of which are real
source fixes (fix(nargs): count Objc block params through count_args,
fix(gates): decide diagnostic-prefix state with a lexer) — and not
this PR, whose only production source change is an import line with no
instrumented regions. Patch coverage is correctly reported as ø.

ci.yml was the only workflow here without workflow_dispatch, so the
sole remedy for a missed main run was to land another commit. Added.

Note it cannot be used to fix this instance until it is on the default
branch — workflow_dispatch resolves against main. Merging this PR
also produces a fresh main run, which re-baselines Codecov either way;
the trigger is for the next time.

Two things checked and found fine, recorded so they are not
re-investigated:

  • Test files are not in the coverage denominator. Codecov's ignore
    lists **/tests/**, which does not match this repo's sibling
    <module>_tests.rs files under src/ (46 files, ~25,920 lines). The
    Codecov API reports zero of them present, so cargo-llvm-cov
    attributes no regions to them. Excluding them recomputes 98.33% to
    98.34%. No change warranted.
  • The patch-vs-project gap is not a defect. Patch measures only
    lines the PR touches; project measures the tree. The 1.67% is
    pre-existing uncovered code in untouched files.

dekobon added 4 commits August 6, 2026 14:15
Dependabot is configured to ignore `version-update:semver-major`, so
these six never arrive on their own: gix 0.83 -> 0.86, sha2 0.10.9 ->
0.11.0, hmac 0.12.1 -> 0.13.0, num-derive 0.4 -> 0.5, clap_mangen 0.2
-> 0.3, and jsonschema 0.46 -> 0.49 (dev only). pyo3 moves 0.29.0 ->
0.29.2, a patch inside the minor its manifest comment guards. Also
refreshes every lockfile: 125 packages in the root workspace and 13-18
in each of the six excluded crates.

Grammar crates are untouched. All twenty plus the tree-sitter runtime
are already at their latest published versions.

One source change: hmac 0.13 splits `KeyInit` out of `Mac`, so
`new_from_slice` needs its own import.

No public-API change. No gix or RustCrypto type appears in a public
signature, so STABILITY.md is unaffected.

Two manifest comments were stale and are corrected here. The sha2 pin
claimed to match a version "locked transitively via grammar crates";
`cargo tree` shows the root crate is now its only dependent. The hmac
comment claimed digest 0.10 added no new trait version, when
actix-http had already brought digest 0.11 into the graph via sha1
0.11 -- which is the island sha2 and hmac now join.

The man pages move because clap_mangen 0.3 renders a required option
after the optional ones in the SYNOPSIS, affecting bca-count and
bca-find.
`uv lock --upgrade` plus regenerated hash-pinned exports, which CI
consumes via `pip install --require-hashes`, so the lockfile and the
exports land together. Notable: mypy 2.1 -> 2.3, pyright 1.1.409 ->
1.1.411, pytest 9.0.3 -> 9.1.1, maturin 1.13.3 -> 1.14.1.

mypy 2.3 is stricter in two places, both in test annotations rather
than in the code under test:

- "too many positional arguments" is now `call-arg`, not `misc`, so
  the existing `type: ignore[misc, arg-type]` had a stale code.
- `inspect.isgenerator`'s `TypeIs` narrowing now propagates into
  `list()`'s argument check, so annotating the target no longer
  recovers the element type. Cast the iterable instead; the comment
  described the old mechanism and is corrected.

ruff stays capped at <0.16. 0.16.1 reports three new diagnostics and
all three are in code written that way deliberately -- DTZ001 on the
naive datetime whose handling is the test's subject, BLE001 on an
intentional `except BaseException`, and PYI044 in a stub. Widening the
bound means adding suppressions to correct code, which is a separate
decision from a dependency refresh.
Every prior assertion on `AuthorId::hashed` and `AuthorHashKey::apply`
was relational -- it compared one digest against another produced by
the same build, so it held whatever the hash library emitted. A
repo-wide search found no 64-hex literal anywhere.

That is the wrong shape for these two, because their output is a
*stored* value with cross-version contracts on both sides.
`src/vcs/cache.rs` writes unkeyed digests to disk and honours them
across version boundaries -- `CACHE_SCHEMA_VERSION` tracks the on-disk
format, not the hash implementation, so a dependency bump does not
invalidate an existing cache -- and `AuthorId::hashed` documents the
emitted digests as stable cross-report pseudonyms.

Expected values are derived from Python's `hashlib` / `hmac`, so the
tests assert conformance to SHA-256 and RFC 2104 rather than agreement
with our own implementation.

Verified by perturbation, per .claude/rules/testing.md. Changing the
SHA-256 pre-image fails both new tests; changing the HMAC pre-image
fails the keyed one. In each case no other test in the 5161-test lib
suite failed -- the pre-existing relational assertions are blind to a
changed hash output, which is the gap these close.

Found while reviewing the sha2 0.10 -> 0.11 / hmac 0.12 -> 0.13 bump in
c490bb6. The digests did not move; nothing in the suite could have
told us.
The suite carries `type: ignore[<code>]` comments and `--strict` turns
on `warn_unused_ignores`, so a stale code is an error rather than a
tolerated no-op. mypy 2.3 reclassified "too many positional arguments"
from `misc` to `call-arg`, so a 2.2-or-older run fails on
`tests/test_metrics_select.py`.

The `>=1.10` floor was already fiction -- the previous `[misc]`
spelling was just as version-specific -- so this states what was
always true rather than tightening anything. The canonical
`make py-bootstrap` path and CI both resolve through the lockfile and
are unaffected; only an un-locked `pip install -e .[dev]` could have
picked a mypy this code does not support.

`requirements/*.txt` are unchanged: the resolution was already at
2.3.0, so only the recorded requirement moved.
@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.33%. Comparing base (f71bcc7) to head (881d942).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #1223   +/-   ##
=======================================
  Coverage   98.33%   98.33%           
=======================================
  Files         278      278           
  Lines       71979    72043   +64     
  Branches    71549    71613   +64     
=======================================
+ Hits        70779    70845   +66     
+ Misses        790      788    -2     
  Partials      410      410           
Flag Coverage Δ
python 100.00% <ø> (ø)
rust 98.32% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/vcs/identity.rs 100.00% <ø> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Every other workflow in .github/workflows/ already has it; ci.yml was
the exception.

The `coverage` job is why it matters. Codecov compares a PR against the
most recent *ancestor that carries a report*, so a push to main that
produces no run leaves every later PR baselined against an older
commit, and the diff table then attributes the intervening commits'
coverage to whichever PR happens to be open.

That is the current state: main's head d818e30 has zero check-runs and
no coverage upload, so PR #1223 is compared against f71bcc7, eight
commits behind. Its reported +64 lines / +66 hits / -2 misses are
almost entirely those eight commits, two of which are real source
fixes -- not the PR they are printed under.

Without a dispatch trigger the only way to recover a missed main run is
to land another commit on main. The failure is silent, so it is worth
being able to fix on demand.
@dekobon
dekobon merged commit 8b51bd2 into main Aug 6, 2026
55 checks passed
@dekobon
dekobon deleted the chore/dep-upgrades branch August 6, 2026 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant