release: 0.6.1 — Layer-1/2/3 ('give the user a chance')#33
Merged
Conversation
Bump version 0.6.0 → 0.6.1. This release lands all three layers
of the 'give the user a chance' design on top of the 0.6.0 P0
hardening pass:
* Layer 1 — structured exception hierarchy. Every public SDK
exception inherits from NullRunError and carries
error_code / user_action / retryable / docs_url / cause.
Five new typed classes (NullRunConfigError, NullRunAuthError,
NullRunBackendError, NullRunBudgetError, NullRunToolBlockedError)
are subclasses of the existing user-facing classes, so every
'except' clause from 0.6.0 keeps matching.
* Layer 2 — nullrun.on_error() global error hook. Fires for
every structured NullRunError before the exception
propagates. Skipped for WorkflowKilledInterrupt (BaseException
subclass — kill is a signal, not an error). Multiple hooks
fire in registration order; hook exceptions are caught and
logged at DEBUG. has_hooks() short-circuit keeps the hot
path zero-cost when no hook is registered.
* Layer 3 — nullrun.status() introspection. Synchronous,
thread-safe, side-effect-free snapshot of runtime state.
Returns a frozen NullRunStatus dataclass with one of four
headline states (ok / degraded / offline / misconfigured).
Raises NullRunConfigError (NR-C004) if no runtime has been
init()'d — never lazily creates a runtime as a side effect.
Per-code docs in docs/errors/ (15 pages + README index).
New tests pin the hierarchy, the hook semantics, the snapshot
fields, and the recent-errors ring buffer.
TestPyPI: the previous 0.6.0 (uploaded 2026-06-23, before
#31 and #32 landed) is yanked separately so the new 0.6.1
wheel can be uploaded. The yank is a TestPyPI-side action;
it does not change the source tree.
c424a20 to
494b487
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bumps version
0.6.0→0.6.1and adds the release-notes entry.The functional work landed in the merged PRs #31 (Layer-1) and
#32 (Layer-2/3); this PR is the release label + CHANGELOG.
What's in 0.6.1
All three layers of the "give the user a chance" design, on top of
the 0.6.0 P0 hardening pass:
NullRunErrorbase + 5 typed subclasses (ConfigError, AuthError, BackendError, BudgetError, ToolBlockedError) witherror_code/user_action/retryable/docs_url/causenullrun.NullRunError,NullRunAuthError,NullRunConfigError,NullRunBackendError,NullRunBudgetError,NullRunToolBlockedError,WorkflowKilledInterruptnullrun.on_error(hook)fires for every structuredNullRunErrorbefore it propagates; multiple hooks fire in registration order; hook exceptions are caught and logged at DEBUG;has_hooks()short-circuit keeps the hot path zero-costnullrun.on_errornullrun.status()returns a frozenNullRunStatusdataclass with one of four headline states (ok/degraded/offline/misconfigured); raisesNullRunConfigError(NR-C004) if no runtime has beeninit()'d; never lazily creates a runtimenullrun.statusPer-code docs:
docs/errors/(15 per-code pages + README index).TestPyPI yank — manual step (REQUIRED before re-running publish)
The previous
0.6.0on TestPyPI (uploaded 2026-06-23, before #31and #32 landed) cannot be silently overwritten — TestPyPI rejects
400 File already existsfor any filename reuse regardless ofcontent hash (see https://test.pypi.org/help/#file-name-reuse).
The publish-test workflow must yank the existing
0.6.0first.Easiest path — web UI:
After the yank, re-run Actions → publish-test → Run workflow on
master(or wait for this PR to merge and run onmaster).If you prefer the CLI (requires a TestPyPI API token with
project scope — not stored in this repo's secrets, only
Trusted-Publishing is wired):
Verification (already done locally on master HEAD)
pytestruff check src/ tests/mypy src/Files in this PR
pyproject.toml—version = "0.6.1"src/nullrun/__version__.py—__version__ = "0.6.1"CHANGELOG.md—## [0.6.1] — 2026-06-24entryAfter merge
0.6.0on TestPyPI (web UI; see above).publish-testworkflow onmaster.0.6.1upload succeeds:pip install -i https://test.pypi.org/simple/ nullrun==0.6.1.