Skip to content

Skip benchmark-ratchet on non-performance pull requests - #289

Open
leynos wants to merge 4 commits into
mainfrom
ci/path-gate-benchmark-ratchet
Open

Skip benchmark-ratchet on non-performance pull requests#289
leynos wants to merge 4 commits into
mainfrom
ci/path-gate-benchmark-ratchet

Conversation

@leynos

@leynos leynos commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Summary

This branch stops the benchmark-ratchet job — the only paid Ubicloud job
in this repository — from running on pull requests that cannot affect
performance. A July 2026 Ubicloud usage audit found the job firing on every
one of 420 CI runs that month, including docs-only edits and Dependabot
github-actions batches, making cuprum the estate's dominant premium-4
consumer.

A new changes job (GitHub-hosted, completes in seconds) classifies the
diff with dorny/paths-filter; benchmark-ratchet now runs on pull
requests only when performance-relevant paths change. Pushes to main are
never gated, because the main run refreshes the
benchmark-ratchet-main-baseline artifact that pull-request runs compare
against. Dependency bumps that touch uv.lock or rust/ still benchmark
by design, since a dependency change can legitimately alter throughput.

A companion commit adds
.github/actionlint.yaml
declaring the ubicloud-standard-4-ubuntu-2404 label, matching the
convention already present in lille, wildside, nile-valley, and chutoro,
so that actionlint passes on this repository's workflows.

Review walkthrough

  • Start with the changes job and the gated needs/if on
    benchmark-ratchet in
    .github/workflows/ci.yml
    — the comments explain why changes runs on every event (a skipped
    needs dependency would otherwise skip the main-branch baseline run).
  • Then .github/actionlint.yaml
    for the runner-label declaration.

Validation

  • actionlint .github/workflows/ci.yml: clean (with the new label
    declaration).
  • uv run pytest cuprum/unittests/test_extension_ci_contract.py cuprum/unittests/test_fetch_main_benchmark_baseline.py -q: 15 passed.

Notes

  • dorny/paths-filter is pinned to the v3.0.2 commit
    (de90cc6f…), consistent with the repository's SHA-pinning policy; the
    grouped github-actions Dependabot ecosystem will keep it updated.
  • If benchmark-ratchet is a required status check, a skipped run counts
    as satisfied, so gated pull requests still merge normally.
  • .github/actionlint.yaml now lists CODESCENE_CLI_SHA256 rather than
    disabling the configuration-variable check, so a typo in a vars.*
    reference is an actionlint error rather than an empty string at run time.
  • One commit here is unrelated housekeeping: the estate-wide typos
    dictionary stopped exempting inline code spans, so regenerating
    typos.toml broke the spelling gate on three pre-existing identifiers.
    They are exempted individually in typos.local.toml rather than by
    reinstating the blanket rule.

Review feedback addressed

  • Tests. cuprum/unittests/test_benchmark_gate_ci_contract.py parses
    ci.yml and asserts the gate: the bench output wiring, the needs
    edge, the gate expression verbatim, the exact filter path set, the
    GitHub-hosted runner for changes, the summary step, and the
    concurrency policy. Property tests (Hypothesis) over sampled changed-path
    sets check the rule those parts encode — any watched path benchmarks
    however it is mixed with docs, a diff touching nothing watched skips, and
    a non-pull-request event always benchmarks. A companion test fails if a
    filter pattern outside the two modelled forms is added, so the path model
    cannot silently stop describing the filter. Verified non-vacuous by
    inverting the gate and deleting a filter path: both mutations fail.
  • Observability. The changes job appends the decision — event, filter
    verdict, and whether the benchmark ran or was skipped — to
    $GITHUB_STEP_SUMMARY on every run. All three fields are closed sets, so
    the summaries stay countable; a skipped job and a broken gate are
    otherwise indistinguishable in the run list.
  • Concurrency and state. The workflow now declares
    concurrency: ci-${{ github.ref }} with cancel-in-progress true only
    for pull requests. Superseded pull-request runs are cancelled; runs on
    main are not, because a cancelled run abandons the baseline upload, and
    queueing them keeps two quick merges from publishing that artifact out of
    commit order.
  • Documentation. "Gating the paid benchmark job" in
    docs/developers-guide.md records the path list, the runner label, the
    main-push behaviour, and why changes is ungated; docs/users-guide.md
    and docs/cuprum-design.md state the gate where they describe the
    ratchet, and ExecPlan 4.4.3 carries an amendment note.

Summary by Sourcery

Gate the paid benchmark-ratchet CI job behind a cheap path-change detector so it only runs when performance-relevant files change, and declare the Ubicloud self-hosted runner label for actionlint.

CI:

  • Add a GitHub-hosted changes job using dorny/paths-filter to detect performance-relevant file changes and expose them as outputs.
  • Update the benchmark-ratchet job to depend on the changes job and run only on main pushes or pull requests that modify performance-related paths.
  • Introduce .github/actionlint.yaml to configure the Ubicloud self-hosted runner label and disable configuration variable checks.

References

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Summary

  • Add a changes job with dorny/paths-filter to detect performance-relevant changes.
  • Run benchmark-ratchet for all pushes to main.
  • Run benchmark-ratchet on pull requests only when relevant paths change.
  • Add .github/actionlint.yaml with the ubicloud-standard-4-ubuntu-2404 runner label.
  • Validate the workflow with clean actionlint output and 15 passing tests.

Walkthrough

Configure actionlint for the self-hosted runner. Add a changes job that detects performance-relevant changes. Run benchmark-ratchet on pushes and on pull requests only when relevant paths change.

Changes

CI benchmark workflow

Layer / File(s) Summary
Configure actionlint validation
.github/actionlint.yaml
Set the self-hosted runner label and disable configuration-variable checks.
Gate benchmark execution
.github/workflows/ci.yml
Add the changes job and use its bench output to conditionally run benchmark-ratchet for pull requests. Keep benchmark execution enabled for pushes.

Poem

Configure the linting gate,
Detect changed paths in sequence,
Run benchmarks on pushes,
Skip untouched pull requests,
Keep the workflow precise.


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 5 warnings)

Check name Status Explanation Resolution
Testing (Overall) ❌ Error The PR adds no tests; existing tests cover benchmark helpers and build steps, not the new paths-filter paths, output, needs edge, or event gating. Add workflow contract tests that parse ci.yml and fail for missing or inverted gating, wrong paths, missing changes dependency, and incorrect push/pull_request conditions.
Developer Documentation ⚠️ Warning The PR adds changes/dorny/paths-filter gating and .github/actionlint.yaml, but docs/developers-guide.md has no documentation for them and no docs files changed. Update docs/developers-guide.md, the benchmark design/user guidance, and ExecPlan 4.4.3 to record the path gate, path list, runner label, and main-push behaviour.
Testing (Unit And Behavioural) ⚠️ Warning The PR adds CI gating in .github/workflows/ci.yml but no tests; the reported tests cover existing benchmark code, while actionlint checks syntax only. Add workflow-boundary contract tests for main pushes, relevant and irrelevant pull-request paths, the filter list, and the benchmark job condition.
Testing (Property / Proof) ⚠️ Warning Flag the missing property-testing recommendation: the new gate varies over event types and arbitrary changed-path sets, but the PR adds no property/model-based test or recommendation. Add a Hypothesis or bounded-model contract test for path-set classification and event gating, covering matching, non-matching, mixed diffs, and main pushes.
Observability ⚠️ Warning Fail this check: the new changes/benchmark-ratchet gate changes paid-runner consumption, but only exposes an internal bench output and adds no bounded metric or explicit decision summary. Add a low-cardinality CI gate signal that records event type, bench result, and benchmark invocation or skip, then document where maintainers can query it.
Concurrency And State ⚠️ Warning benchmark-ratchet now depends on changes and writes the shared main baseline, but ci.yml has no concurrency policy and no tests cover skipped PRs or out-of-order baseline runs. Add an explicit baseline ordering or concurrency policy, and add workflow contract tests for PR gating, main refresh, dependency failure, and out-of-order main runs.
✅ Passed checks (14 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
User-Facing Documentation ✅ Passed Document no user-facing change: the PR modifies only GitHub Actions CI infrastructure, while the users’ guide and README remain unchanged.
Module-Level Documentation ✅ Passed The PR changes only .github/actionlint.yaml and .github/workflows/ci.yml; it adds or modifies no source module, so module-level documentation is not applicable.
Testing (Compile-Time / Ui) ✅ Passed Pass this check: the cumulative diff contains only GitHub Actions YAML; it adds no Rust/TypeScript compile-time behaviour or user-facing output that warrants snapshot tests.
Unit Architecture ✅ Passed Pass this check: the PR changes only declarative CI/config files; changes exposes an explicit bench output and benchmark-ratchet uses explicit needs and if boundaries.
Domain Architecture ✅ Passed Keep this change: the patch adds only GitHub Actions workflow gating and actionlint configuration; no domain, adapter, persistence, transport, or application logic changed.
Security And Privacy ✅ Passed The workflow additions use pinned actions, read-only contents and pull-request permissions, and contain no secret values or privileged write access.
Performance And Resource Use ✅ Passed The change adds one bounded path-classification job and a conditional benchmark job; it introduces no hot-path algorithm, unbounded collection, retry loop, or repeated per-item I/O.
Architectural Complexity And Maintainability ✅ Passed Keep this design: it adds one explicit changes job, a pinned existing-style action, and a direct dependency edge; actionlint passes and no code-layer abstraction or cycle is introduced.
Rust Compiler Lint Integrity ✅ Passed The PR changes only .github/actionlint.yaml and .github/workflows/ci.yml; it adds no Rust code, lint suppression, artificial reference, or clone call.
Title check ✅ Passed The title clearly describes gating benchmark-ratchet for non-performance pull requests, which matches the main change.
Description check ✅ Passed The description directly explains the CI gating changes, runner configuration, validation, and related documentation updates.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/path-gate-benchmark-ratchet

Comment @coderabbitai help to get the list of available commands.

codescene-access[bot]

This comment was marked as outdated.

@sourcery-ai

sourcery-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds a lightweight changes classification job to CI and gates the paid benchmark-ratchet workflow on performance-relevant file changes, plus configures actionlint to recognize the Ubicloud runner label.

Flow diagram for gating benchmark-ratchet on performance-relevant changes

flowchart LR
  GitHubEvent[GitHub event]
  ChangesJob[changes job]
  PathsFilter[dorny/paths-filter]
  BenchOutput{needs.changes.outputs.bench}
  BenchmarkRatchet[benchmark-ratchet job]

  GitHubEvent --> ChangesJob
  ChangesJob --> PathsFilter
  PathsFilter --> BenchOutput

  BenchOutput -- pull_request and bench == 'true' --> BenchmarkRatchet
  GitHubEvent -- event_name != 'pull_request' --> BenchmarkRatchet
Loading

File-Level Changes

Change Details Files
Introduce a changes classification job to detect performance-relevant diffs and expose an output flag for downstream jobs.
  • Add a changes job running on ubuntu-latest with minimal read permissions for contents and pull-requests.
  • Use dorny/paths-filter (pinned by commit SHA) to define a bench filter matching performance-relevant paths such as cuprum/, rust/, benchmarks/, core config files, and CI workflow YAML.
  • Expose the bench result via job outputs for consumption by other jobs.
.github/workflows/ci.yml
Gate benchmark-ratchet execution on the changes job output so benchmarks only run when needed, while preserving always-on behavior for main branch pushes.
  • Add changes as a needs dependency of benchmark-ratchet to ensure the classification step runs before benchmarks.
  • Add an if condition combining event type and changes.bench output so benchmark-ratchet runs on all non-pull_request events and only on pull requests with performance-relevant changes.
  • Document the cost rationale and behavior of the gating logic directly in the workflow comments.
.github/workflows/ci.yml
Configure actionlint to understand the Ubicloud self-hosted runner label and disable configuration variable checks.
  • Add .github/actionlint.yaml with a self-hosted-runner.labels entry for ubicloud-standard-4-ubuntu-2404.
  • Set config-variables to null to disable config variable checking in actionlint.
.github/actionlint.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@leynos
leynos marked this pull request as ready for review August 5, 2026 20:54
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

codescene-access[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/actionlint.yaml:
- Line 9: Update the config-variables setting in actionlint.yaml from null to an
allow-list containing only CODESCENE_CLI_SHA256, matching the sole vars.*
workflow variable.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 16a12af4-b20a-4299-906c-ee4719a4b012

📥 Commits

Reviewing files that changed from the base of the PR and between b1e6452 and 8871cdc.

📒 Files selected for processing (2)
  • .github/actionlint.yaml
  • .github/workflows/ci.yml
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/shared-actions (auto-detected)
  • leynos/pylint-pypy-shim (auto-detected)
  • leynos/whitaker (auto-detected)

Comment thread .github/actionlint.yaml Outdated
# Configuration variables in array of strings defined in your repository or
# organization. `null` means disabling configuration variables check.
# Empty array means no configuration variable is allowed.
config-variables: null

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- actionlint configuration ---'
cat -n .github/actionlint.yaml

printf '%s\n' '--- vars references in workflows ---'
rg -n --glob '*.yml' --glob '*.yaml' \
  '\bvars\.[A-Za-z_][A-Za-z0-9_]*\b' .github || true

printf '%s\n' '--- actionlint version/config references ---'
rg -n -i 'actionlint|config-variables' \
  .github Makefile* pyproject.toml setup.cfg tox.ini .pre-commit-config.yaml 2>/dev/null || true

printf '%s\n' '--- workflow files ---'
git ls-files '.github/workflows/*.yml' '.github/workflows/*.yaml'

Repository: leynos/cuprum

Length of output: 1234


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

root = Path(".github")
pattern = re.compile(r"\bvars\.([A-Za-z_][A-Za-z0-9_]*)\b")
references = {}
for path in sorted(root.rglob("*")):
    if path.suffix not in {".yml", ".yaml"} or "workflows" not in path.parts:
        continue
    text = path.read_text()
    names = sorted(set(pattern.findall(text)))
    if names:
        references[str(path)] = names

print("workflow vars names:", sorted({name for names in references.values() for name in names}))
for path, names in references.items():
    print(f"{path}: {', '.join(names)}")

config = Path(".github/actionlint.yaml").read_text()
match = re.search(r"(?m)^config-variables:\s*(.*)$", config)
print("config-variables entry:", match.group(1).strip() if match else "<missing>")
PY

Repository: leynos/cuprum

Length of output: 331


🌐 Web query:

actionlint config-variables null allow-list configuration semantics

💡 Result:

In actionlint, the config-variables configuration option is used to define an allow-list for configuration variables (vars context) used within GitHub Actions workflows [1][2]. The semantics of the config-variables setting are as follows: 1. When set to an array of strings, actionlint performs strict validation on the vars context [1][2]. Any variable referenced in the workflow that is not present in this list will be reported as an undefined configuration variable [3]. 2. When set to an empty array ([]), no configuration variables are permitted; any use of the vars context will be flagged [1][2]. 3. The default value is null, which disables the validation check entirely, meaning actionlint will not attempt to verify the names of configuration variables used in the workflows [1][3][2]. This configuration is typically defined within an actionlint.yaml or actionlint.yml file located in the.github directory of the repository [1].

Citations:


Set config-variables to an allow-list.

Replace null with CODESCENE_CLI_SHA256, the only vars.* name used by the workflows.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/actionlint.yaml at line 9, Update the config-variables setting in
actionlint.yaml from null to an allow-list containing only CODESCENE_CLI_SHA256,
matching the sole vars.* workflow variable.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

leynos and others added 4 commits August 8, 2026 02:01
`actionlint` rejects `ubicloud-standard-4-ubuntu-2404` as an unknown
runner label without a `self-hosted-runner` declaration. The other
Ubicloud-using repositories in the estate (lille, wildside,
nile-valley, chutoro) already carry `.github/actionlint.yaml` for this
reason; bring cuprum in line so workflow changes can be linted.
`benchmark-ratchet` is the only paid Ubicloud job in this workflow,
and a July 2026 usage audit found it running on every one of 420 CI
runs — including docs edits and Dependabot github-actions batches that
cannot change pipeline throughput.

Add a `changes` job (GitHub-hosted, seconds) that classifies the diff
with `dorny/paths-filter`, and gate `benchmark-ratchet` on it for pull
requests. Performance-relevant paths — `cuprum/`, `rust/`,
`benchmarks/`, `conftest.py`, the `Makefile`, `pyproject.toml`,
`uv.lock`, and the workflow itself — still trigger the ratchet, so
dependency bumps that could alter performance are still measured.

Pushes to main are never gated: the ratchet must run there to refresh
the `benchmark-ratchet-main-baseline` artifact that pull-request runs
compare against. The `changes` job itself runs on every event so the
`needs` edge cannot leave `benchmark-ratchet` skipped on main.
The estate-wide typos base no longer exempts inline code spans wholesale,
so regenerating typos.toml drops the rule the committed copy still carried
and three real identifiers start failing the spelling gate: a helper name,
a third-party command-line flag, and the style guide's own example of a
US-spelled API name.

Exempt them one at a time in typos.local.toml rather than reinstating the
blanket rule; prose inside backticks should still be spell-checked. Commit
the regenerated typos.toml so the gate stops re-deriving the drift.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The gate in front of benchmark-ratchet lives entirely in declarative
configuration, and every part of it fails silently in the direction that
costs money or hides a regression: invert the condition and a genuine
performance change merges unbenchmarked, drop the event clause and pushes
to main stop refreshing the baseline that pull-request runs compare
against. No ordinary test notices, so parse ci.yml and assert the contract
— the bench output wiring, the needs edge, the gate expression verbatim,
the exact filter path set, and the runner the detector uses. Property
tests over sampled changed-path sets then check the rule those parts
encode, against a path model a companion test stops from drifting away
from the filter it claims to describe.

Record the decision — event, filter verdict, ran or skipped — in the run
summary of every run, because a skipped job and a broken gate look
identical in the run list, and this gate exists to be audited against
paid-runner spend.

Add a per-ref concurrency policy while here. Superseded pull-request runs
are cancelled, since a stale run only spends benchmark minutes on a diff
nobody will merge; runs on main are not, because cancelling one abandons
the baseline upload, and queueing them keeps two quick merges from
publishing that artifact out of commit order.

Narrow actionlint's config-variables to the one variable the workflows
read, so a typo in a vars.* reference is an error rather than an empty
string at run time.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lodyai
lodyai Bot force-pushed the ci/path-gate-benchmark-ratchet branch from 22ac97a to d80b30d Compare August 8, 2026 00:06
codescene-access[bot]

This comment was marked as outdated.

@codescene-access codescene-access Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No quality gates enabled for this code.

@leynos

leynos commented Aug 8, 2026

Copy link
Copy Markdown
Owner Author

Two red checks on this branch are pre-existing and unrelated to the change; recording the evidence.

benchmark-ratchet — the current main baseline contains an outlier.
After rebasing, this branch's runtime code is identical to main, yet the ratchet reports a 0.46 regression. Three of the four scenarios agree closely with the baseline; one does not:

scenario baseline ratio candidate ratio regression
medium-single-cb 0.916 1.047 +0.143
medium-single-nocb 0.760 1.110 +0.461
small-single-cb 1.105 1.088 −0.016
small-single-nocb 1.166 1.076 −0.077

That 0.760 comes from the main run at 7f6ec92, which measured medium-single-nocb at 0.760 against its own baseline of 1.013 — a −25% swing it recorded as a pass and then published as the new baseline. The candidate's 1.110 is in line with its three siblings; the baseline entry is the outlier. Every pull request will fail this scenario until a main push republishes a representative baseline. Worth a follow-up on the ratchet's noise handling rather than a change here.

Python 3.15a fails four test_non_positive_timeout_at_public_boundary cases on a CPython 3.15 alpha change to TimeoutExpired.output. That row is continue-on-error, and #293 is addressing it.

All local commit gates pass on the rebased branch: make check-fmt, make lint, make typecheck, make test, make markdownlint, make nixie.

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