Skip to content

docs: add logo and shields.io badges to README#18

Merged
maltsev-dev merged 1 commit into
masterfrom
docs/logo-and-badges
Jun 19, 2026
Merged

docs: add logo and shields.io badges to README#18
maltsev-dev merged 1 commit into
masterfrom
docs/logo-and-badges

Conversation

@maltsev-dev

Copy link
Copy Markdown
Member

Summary

Adds the NullRun logo and a set of shields.io badges to the top of README.md so the package page on PyPI renders the brand identity at a glance.

Changes

  • docs/nullrun-logo.png (new file, 325 KB) — the NullRun NR mark. Hosted in-repo so it is reachable from the rendered README on PyPI via github.com/ghraw (HTTPS only — PyPI strips http images).
  • README.md — adds two badge rows at the top, above the existing heading:
    • Release: PyPI version, Python versions, License, Downloads
    • Quality/Project: CI, Coverage, Stars, Documentation

All badges link to the corresponding real page (PyPI, GitHub Actions, Codecov, docs.nullrun.io).

Diff scope

README.md             |  35 +++++++++++++++++++++++++++++++++++
docs/nullrun-logo.png | Bin 0 -> 325059 bytes

Why

  • PyPI currently renders only plain text. A logo + badges make the package discoverable and signal project health, matching how nullout-mcp and other ecosystem packages present themselves.
  • All badges are https:// only (PyPI readme-sanitiser requirement).

Out of scope

  • pyproject.toml classifiers — left as-is per project decision.
  • The @protect example form in README — kept exactly as on master.

- Add docs/nullrun-logo.png (NullRun NR logo) and render it centered
  at the top of README.md via github.com/ghraw
- Add shields.io badges in two rows:
  * Release: PyPI version, Python versions, License, Downloads
  * Quality/Project: CI, Coverage, Stars, Documentation
- All badges use https:// (PyPI readme sanitizer strips http://)
- No classifier changes (left as-is per project decision)
@maltsev-dev maltsev-dev merged commit 078867f into master Jun 19, 2026
0 of 4 checks passed
@maltsev-dev maltsev-dev deleted the docs/logo-and-badges branch June 19, 2026 06:42
maltsev-dev added a commit that referenced this pull request Jul 3, 2026
Task #3 / Task #18 (2026-07-03): wire the SDK to the backend's
v3 default. Per CLAUDE.md §24, every /check mints a
server-side uuidv7 execution_id; the SDK receives it in the
response and propagates it to /track.

This is the SDK_MIN_VERSION for the v3 rollout per CLAUDE.md
§0 pre-flip checklist.

Changes:

src/nullrun/uuid7.py (new):
- RFC 9562 §5.7 time-ordered ID generator. 48-bit unix_ts_ms
  prefix + 12-bit rand_a + 62-bit rand_b. Same layout as the
  backend's mint_execution_id() so log scrapers can sort by
  ID alone.
- Uses secrets.token_bytes(10) for cryptographically secure
  random component.
- uuid7() returns stdlib UUID; uuid7_str() returns the
  canonical 36-char string.

src/nullrun/capabilities.py (new):
- ServerCapabilities dataclass mirrors /health payload.
- is_v3_ready() returns True only when ALL three v3 caps
  (server_minted_execution_id, per_execution_reservations,
  heartbeat_time_based) are set.
- probe_capabilities(api_url) — best-effort /health fetch
  with 2s timeout. Returns None on failure (not fatal).
- validate_sdk_version(sdk_version, caps) — returns warnings
  for SDK_MIN_VERSION mismatch.
- SDK_MIN_VERSION_FOR_V3 = '0.12.0' is the gate's coordinate
  for the v3 rollout.

src/nullrun/__init__.py:
- init() now probes /health after singleton registration and
  logs a startup warning for version mismatch (does NOT fail
  init() — the gate still rejects with PROTOCOL_TOO_OLD).
- Probe is best-effort: timeout/5xx logs at INFO.

src/nullrun/__version__.py:
- Bumped 0.11.0 → 0.12.0 (the SDK_MIN_VERSION coordinate).

CHANGELOG.md:
- New 0.12.0 entry with Added/Changed sections.

tests/test_uuid7.py (new): 8 tests pin the wire contract:
- Returns stdlib UUID
- 36-char string format
- Version bits = 7
- Variant bits = 0b10
- Time-ordered (consecutive calls sort)
- 1000 unique IDs under rapid calls
- Round-trips through uuid.UUID()

tests/test_capabilities.py (new): 9 tests pin:
- v3-ready backend parses to is_v3_ready()=True
- Missing keys default to False (fail-closed)
- Partial v3 caps → not ready
- Old SDK against v3 backend → warning
- Current SDK → no warning
- Legacy backend → 'not v3-ready' warning
- Unparseable versions don't crash
- as_dict() is wire-safe (no secrets)
- SDK_MIN_VERSION_FOR_V3 = '0.12.0'

Tests: 17 new SDK tests pass. Full backend test suite still
green at 1443.
maltsev-dev added a commit that referenced this pull request Jul 3, 2026
* feat(sdk): server-minted execution_id default — uuid7 + capability probe

Task #3 / Task #18 (2026-07-03): wire the SDK to the backend's
v3 default. Per CLAUDE.md §24, every /check mints a
server-side uuidv7 execution_id; the SDK receives it in the
response and propagates it to /track.

This is the SDK_MIN_VERSION for the v3 rollout per CLAUDE.md
§0 pre-flip checklist.

Changes:

src/nullrun/uuid7.py (new):
- RFC 9562 §5.7 time-ordered ID generator. 48-bit unix_ts_ms
  prefix + 12-bit rand_a + 62-bit rand_b. Same layout as the
  backend's mint_execution_id() so log scrapers can sort by
  ID alone.
- Uses secrets.token_bytes(10) for cryptographically secure
  random component.
- uuid7() returns stdlib UUID; uuid7_str() returns the
  canonical 36-char string.

src/nullrun/capabilities.py (new):
- ServerCapabilities dataclass mirrors /health payload.
- is_v3_ready() returns True only when ALL three v3 caps
  (server_minted_execution_id, per_execution_reservations,
  heartbeat_time_based) are set.
- probe_capabilities(api_url) — best-effort /health fetch
  with 2s timeout. Returns None on failure (not fatal).
- validate_sdk_version(sdk_version, caps) — returns warnings
  for SDK_MIN_VERSION mismatch.
- SDK_MIN_VERSION_FOR_V3 = '0.12.0' is the gate's coordinate
  for the v3 rollout.

src/nullrun/__init__.py:
- init() now probes /health after singleton registration and
  logs a startup warning for version mismatch (does NOT fail
  init() — the gate still rejects with PROTOCOL_TOO_OLD).
- Probe is best-effort: timeout/5xx logs at INFO.

src/nullrun/__version__.py:
- Bumped 0.11.0 → 0.12.0 (the SDK_MIN_VERSION coordinate).

CHANGELOG.md:
- New 0.12.0 entry with Added/Changed sections.

tests/test_uuid7.py (new): 8 tests pin the wire contract:
- Returns stdlib UUID
- 36-char string format
- Version bits = 7
- Variant bits = 0b10
- Time-ordered (consecutive calls sort)
- 1000 unique IDs under rapid calls
- Round-trips through uuid.UUID()

tests/test_capabilities.py (new): 9 tests pin:
- v3-ready backend parses to is_v3_ready()=True
- Missing keys default to False (fail-closed)
- Partial v3 caps → not ready
- Old SDK against v3 backend → warning
- Current SDK → no warning
- Legacy backend → 'not v3-ready' warning
- Unparseable versions don't crash
- as_dict() is wire-safe (no secrets)
- SDK_MIN_VERSION_FOR_V3 = '0.12.0'

Tests: 17 new SDK tests pass. Full backend test suite still
green at 1443.

* fix(sdk): populate Author/Author-email via metadata hook

PEP 621 maps `authors` to PKG-INFO's `Author-email:` line but not to the
legacy single `Author:` line that `pip show` renders, and pip does
not display `Maintainer:` either. As a result every previous release
shipped with an empty `Author:` and the maintainer's name never
appeared in `pip show nullrun`.

Hatchling compounds this: its authors parser only adds an entry to
`authors_data["name"]` (which becomes `Author:`) when an
inline-table has a `name` and NO `email`. When both are present the
name is folded into `Author-email:`'s display_name and the legacy
`Author:` line is suppressed entirely.

Fix: declare `authors` and `maintainers` as dynamic fields and
populate them from a custom hatchling metadata hook
(`hatch_build.py`). The hook splits the primary author into a
name-only + email-only inline-table pair so hatchling populates both
`Author:` and `Author-email:`. Declaring at least one dynamic field
is what actually wires `MetadataHookInterface.update()` — without it
hatchling configures the hook but never invokes it.

* fix(sdk): bind logger in init() and cover capability probe paths

CI on Python 3.11 failed with `NameError: name 'logger' is not defined`
in 5 tests. The `feat(sdk)` commit (2a7886b) added new
`logger.warning/info/debug` calls in `init()` after the existing
`import logging` but never assigned the `logger` name. Master
passed only because its pre-existing `logger.warning` calls sit
inside an `if existing is not None:` branch that tests rarely
exercise; the new ones run on every `init()` call.

Also covers the 9 newly-uncovered lines Codecov flagged:
`probe_capabilities` failure paths (non-2xx / ConnectError /
malformed JSON) and the four new `init()` logging branches
(`debug=True` sets DEBUG; probe unreachable → INFO; probe raises
→ DEBUG; existing runtime shutdown raises → WARNING).

Local verification (.venv-ci, Python 3.14):
- pytest: 1154 passed (was 1129; +25 new)
- ruff: clean
- mypy: clean
- coverage: 82.02% (threshold 82.00%)

* style: reorder capability probe imports per ruff I001

Ruff's isort rule flagged the import block in `init()` — the
`from nullrun.__version__` line was placed after
`from nullrun.capabilities` but `__version__` sorts before
`capabilities` (underscore is 0x5F, letters are 0x61+), so the
correct alphabetical order is reversed.

CI `Run ruff` step was failing on this; the previous commit's
ruff output was checked against an outdated working copy.
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