Skip to content

Commit dcf4cc6

Browse files
authored
chore(release): 0.18.5 — curated-surface reduction (handle→guard, init(fail_on_exit), drop framework extras + auto_instrument) (#112)
## Summary Cut `v0.18.5` — the consolidated release that ships the deprecation sweep, the 0.18.3 `init`/`init_or_die` unification, the 0.18.4 `handle` → `guard` rename plus top-level `status()` removal, and the mechanical lint/type cleanup that brings `ruff check src tests` and `mypy src/nullrun` back to green after the 1882-insertion / 15621-deletion sweep. All the substantive work landed on master via #111 (squash `aee8110`); the only change in this release PR is the version stamp + CHANGELOG consolidation + `uv.lock` regen. The user-facing surface shrinks to 21 curated symbols (down 6 from 0.18.2): `__version__`, `init`, `protect`, `shutdown`, `on_error`, `guard`, the typed exception catalog (8 classes), `WorkflowKilledInterrupt`, `format_user_message`, `set_user_message`. The single user-facing entry point for tool-call gating remains `\`@protect\`` (now wired unconditionally through `/api/v1/execute`); `\`@guarded\`` and `\`@handle\`()` are removed. `nullrun.init_or_die()` is removed in favour of `nullrun.init(fail_on_exit=True)`. Top-level `nullrun.status()` is removed in favour of `nullrun.get_runtime().status()`. ### Themes 1. **Public-surface reduction (cumulative since 0.18.2)** - `nullrun.handle` → `nullrun.guard` (rename, same `@contextmanager` body) — `83421e0`. - Top-level `nullrun.status()` removed; reach via `nullrun.get_runtime().status()` — `83421e0`. - `nullrun.init_or_die()` removed; `nullrun.init(fail_on_exit=True)` replaces it — `ccb2670`. - `nullrun.shutdown()` auto-registered via `atexit` inside `init()` — `ccb2670`. - `\`@guarded\`` decorator dropped (was a 3-line shortcut for `with nullrun.guard():`) — `f1721f2`. - Framework-extras install groups dropped from `pyproject.toml` (`[agents]`, `[langchain]`, `[langgraph]`, `[llama-index]`, `[crewai]`, `[autogen]`); `pip install nullrun` is now the only public install line — `57225e9`. - `auto_instrument` / `is_auto_instrumented` removed from `_LAZY_EXPORTS`; module-level `track_event` alias removed; `NullRunCallback` removed from `_LAZY_EXPORTS` — `57225e9`. 2. **Internal-surface cleanup (not user-visible)** - `src/nullrun/business_impact.py` narrows `BusinessImpact.impact: Any` → `NoImpactPayload` (the inline comment already documented the invariant; the only public ctor wires a `NoImpactPayload`, so the broader `Any` was masking a real `no-any-return` at the `to_wire_dict` boundary). - `src/nullrun/__init__.py` tightens `_LAZY_EXPORTS` annotation from `tuple[str, str | None]` → `tuple[str, str]` (every value in the table is a 2-tuple of strings; the optional was wrong). - 71 unused imports (F401) auto-removed across `src/nullrun/` and `tests/`; 9 unused locals (F841) hand-removed in `test_actions.py`, `test_ws_signed_payload.py`, `test_transport.py`, `test_signal_safety.py`, `test_autogen_patch.py`, `test_dedup.py`, `test_model_fallback.py`, `test_registry.py` — all dead code left behind after the 15621-line deletion sweep. 3. **Documentation cleanup** - Strips "pre-fix / post-fix", "previously / now we", "was X / is now Y", and "legacy" framing from public docstrings across `runtime.py`, `transport.py`, `decorators.py`, and 14 other modules. External ticket identifiers (DEF-*, ADR-*, AUDIT P*, IDEM-01, CLOSE-ORPHAN) preserved as anchors — `15e4fad`, `9595d6e`, `d0d0e72`. - Follow-up rename sweep in `docs/` and `scripts/` to match the 0.18.4 `handle`→`guard` change — `bf30566`. ### CHANGELOG The `## [0.18.5] - 2026-09-26` block at the top of `CHANGELOG.md` consolidates the entries the original commits wrote for the never- released 0.18.3 and 0.18.4 versions; both of those blocks are removed from the user-facing CHANGELOG because those versions were never shipped. The git history of `aee8110` (squash of #111) preserves the original per-commit documentation if needed for traceability. ### Cleanup - `.gitignore` already covers `dist_local/` and `src/**/*.defect*` from a previous release scrub; no new artifacts shipped in this release. - `uv.lock` regenerated: prior lock was at `0.18.0` and still carried the framework-extras dependency tree (sse-starlette, textual, sympy, watchfiles, websocket-client, wrapt, yarl, …). The new lock reflects `0.18.5` with only the core runtime deps (httpx) plus `[opentelemetry]` and `[dev]` extras. +196 / −4863. ### Tooling - `ruff check src tests` clean. - `mypy src/nullrun` clean — `Success: no issues found in 36 source files`. - `pytest -q` clean — `1401 passed, 1 skipped` in 74.60s (baseline at 0.18.1 was 1784 passed / 4 skipped; net −383 tests reflects removal of `test_handle`, `test_protect`+branches, `test_observability`, `test_preflight_fail_policy`, `test_tool_params_extractor`, `test_units_discriminator`, `test_sensitive_extractor`, `test_execute_*`, `test_approval_*`, `test_money_hardening`, `test_args_pii_masked` and friends as the surface they tested was removed). ### Verification | Check | Result | |---|---|---| | `ruff check src tests` | All checks passed | | `mypy src/nullrun` | Success: no issues found in 36 source files | | `pytest -q` | **1401 passed, 1 skipped** in 74.60s | | Scratch diff | clean (`.gitignore` covers `dist_local/`, `src/**/*.defect*`) | | `python -c "import nullrun; print(nullrun.__version__)"` | `0.18.5` | | Wire-format compatibility | unchanged from 0.18.0 | ### Commits included ``` 0ea439b fix errors (this commit, will be amended) ``` The substantive work for 0.18.5 landed on master via #111 (squash `aee8110`) prior to this release PR; per-commit detail lives in that PR's thread.
1 parent aee8110 commit dcf4cc6

4 files changed

Lines changed: 272 additions & 4900 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 74 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,59 @@
1-
## [0.18.4] - 2026-09-25
1+
## [0.18.5] - 2026-09-26
2+
3+
Consolidated release that bundles three rounds of work landed on
4+
`cleanup/deprecation-removal` (#111) and never shipped as separate
5+
versions: the 0.18.3 `init`/`init_or_die` unification, the 0.18.4
6+
`handle` → `guard` rename plus top-level `status()` removal, and
7+
the follow-on deprecation sweep (drop redundant `@guarded`, drop
8+
framework-extras / `auto_instrument` public surface, strip legacy
9+
"pre-fix / post-fix" docstring framing, drop stale `init_or_die`
10+
references in source docstrings). Also adds a mechanical lint/type
11+
cleanup pass that brings `ruff check src tests` and `mypy
12+
src/nullrun` back to green after the 1882-insertion / 15621-deletion
13+
sweep across the branch (71 unused imports, 9 unused locals,
14+
`BusinessImpact.impact` narrowed from `Any` to `NoImpactPayload`,
15+
`_LAZY_EXPORTS` annotation tightened).
216

317
### Surface (breaking)
418

5-
- `nullrun.handle` renamed to `nullrun.guard`. Same `@contextmanager`
6-
body (catches `NullRunError`, re-raises `WorkflowKilledInterrupt`,
7-
renders the four-line developer report, `sys.exit(1)` on failure).
8-
The name `guard` was freed in 0.18.2 when `@guarded` was removed.
9-
Migrate by replacing `from nullrun import handle` /
10-
`with nullrun.handle:` with `from nullrun import guard` /
11-
`with nullrun.guard():`.
19+
- `nullrun.handle` renamed to `nullrun.guard`. Same
20+
`@contextmanager` body (catches `NullRunError`, re-raises
21+
`WorkflowKilledInterrupt`, renders the four-line developer report,
22+
`sys.exit(1)` on failure). The name `guard` was freed when
23+
`@guarded` was dropped earlier in this release. Migrate by
24+
replacing `from nullrun import handle` / `with nullrun.handle:`
25+
with `from nullrun import guard` / `with nullrun.guard():`.
1226
- Top-level `nullrun.status()` removed. Reach the snapshot via
1327
`nullrun.get_runtime().status()` (returns the same frozen
1428
`NullRunStatus` dataclass). The wrapper's only role was raising
1529
`NullRunConfigError(NR-C004)` when no runtime was bound — that
1630
path is now `get_runtime()`'s job. `NullRunStatus` itself
1731
remains importable as a type.
18-
19-
### Curated surface after 0.18.4
20-
21-
```text
22-
__version__, init, protect, shutdown, on_error, guard,
23-
NullRunError, NullRunAuthError, NullRunConfigError,
24-
NullRunBackendError, NullRunBudgetError, NullRunToolBlockedError,
25-
WorkflowKilledInterrupt, NullRunWorkflowKilledError,
26-
NullRunMcpDestructiveBlockedError,
27-
NullRunMcpReadonlyBypassBlockedError,
28-
NullRunMcpApprovalRequiredError,
29-
NullRunApprovalDbUnavailableError,
30-
format_user_message, set_user_message
31-
```
32-
33-
(`status` and `handle` dropped; `guard` added. Net -1 symbol vs 0.18.3.)
34-
35-
## [0.18.3] - 2026-09-25
36-
37-
### Surface (breaking)
38-
3932
- `nullrun.init_or_die()` removed. CLI fail-fast behavior is now a
40-
parameter on `init()`: `nullrun.init(fail_on_exit=True)` prints the
41-
same four-line developer report and `sys.exit(1)` on configuration
42-
failure.
33+
parameter on `init()`: `nullrun.init(fail_on_exit=True)` prints
34+
the same four-line developer report and `sys.exit(1)` on
35+
configuration failure.
4336
- `nullrun.shutdown()` is now auto-registered via `atexit` inside
4437
`init()` — long-running scripts get a clean WS close on process
4538
exit without an explicit call. Calling `shutdown()` manually
4639
remains safe and idempotent.
40+
- `@nullrun.guarded` decorator removed. It was a 3-line syntactic
41+
shortcut for `with nullrun.guard():`; with `guard` as the
42+
canonical error-translation path the decorator form was pure
43+
duplication.
44+
- Framework-extras install groups dropped from `pyproject.toml`
45+
(`[agents]`, `[langchain]`, `[langgraph]`, `[llama-index]`,
46+
`[crewai]`, `[autogen]`). The silent auto-detect instrumentation
47+
patches remain in code, but `nullrun` no longer advertises
48+
per-framework install paths or example wiring. Public install
49+
is one line: `pip install nullrun`.
50+
- `nullrun.auto_instrument` / `nullrun.is_auto_instrumented`
51+
removed from the top-level namespace (they were internal
52+
triggers, not user-facing API). Module-level `track_event`
53+
alias removed (duplicate of `track`; the `runtime.track_event`
54+
method is still used internally). `NullRunCallback` removed
55+
from `_LAZY_EXPORTS` (advanced / manual path; reachable via
56+
`nullrun.toolbox.langgraph` if ever needed).
4757

4858
### Lifecycle
4959

@@ -54,8 +64,37 @@ format_user_message, set_user_message
5464
- The `_shutdown_atexit_registered` module-level flag prevents
5565
double registration when `init()` is called more than once.
5666

57-
Top-level `dir(nullrun)` no longer exposes `init_or_die`. All other
58-
symbols unchanged from 0.18.2.
67+
### Tooling
68+
69+
- Strips "pre-fix / post-fix", "previously / now we", "was X / is
70+
now Y", and "legacy" framing from public docstrings across
71+
`runtime.py`, `transport.py`, `decorators.py`, and 14 other
72+
modules. External ticket identifiers (DEF-*, ADR-*, AUDIT P*,
73+
IDEM-01, CLOSE-ORPHAN) are preserved as anchors.
74+
- Mechanical lint cleanup: 71 unused imports (F401) auto-removed,
75+
9 unused locals (F841) hand-removed across `tests/`. `ruff check
76+
src tests` and `mypy src/nullrun` are clean on the merged
77+
branch.
78+
79+
### Curated surface after 0.18.5
80+
81+
```text
82+
__version__, init, protect, shutdown, on_error, guard,
83+
NullRunError, NullRunAuthError, NullRunConfigError,
84+
NullRunBackendError, NullRunBudgetError, NullRunToolBlockedError,
85+
WorkflowKilledInterrupt, NullRunWorkflowKilledError,
86+
NullRunMcpDestructiveBlockedError,
87+
NullRunMcpReadonlyBypassBlockedError,
88+
NullRunMcpApprovalRequiredError,
89+
NullRunApprovalDbUnavailableError,
90+
format_user_message, set_user_message
91+
```
92+
93+
(Net vs 0.18.2: `status`, `handle`, `guarded`, `init_or_die`,
94+
`auto_instrument`, `is_auto_instrumented`, `track_event` removed;
95+
`guard` added. Net -6 symbols vs 0.18.2.)
96+
97+
Wire contract: unchanged from 0.18.0.
5998

6099
## [0.18.2] - 2026-09-22
61100

@@ -77,4 +116,4 @@ Top-level `dir(nullrun)` exposes only:
77116
`NullRunMcpReadonlyBypassBlockedError`, `NullRunToolBlockedError`,
78117
`NullRunWorkflowKilledError`, `WorkflowKilledInterrupt`)
79118

80-
Wire contract: unchanged from 0.18.0.
119+
Wire contract: unchanged from 0.18.0.

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
66
name = "nullrun"
77
# Full release history lives in CHANGELOG.md; only the current version
88
# is pinned here.
9-
version = "0.18.4"
9+
version = "0.18.5"
1010
# Kept under the 200-char preview threshold so the full line is visible
1111
# without an "expand" click. The headline is the canonical §1 statement
1212
# from positioning.md — "runtime decision layer for tool-using AI agents"

‎src/nullrun/__version__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
string and the SDK_MIN_VERSION constant.
66
"""
77

8-
__version__ = "0.18.4"
8+
__version__ = "0.18.5"
99
__platform_version__ = "1.0.0"

0 commit comments

Comments
 (0)