Skip to content

Dev - #4

Merged
a9lim merged 5 commits into
mainfrom
dev
Apr 26, 2026
Merged

Dev#4
a9lim merged 5 commits into
mainfrom
dev

Conversation

@a9lim

@a9lim a9lim commented Apr 26, 2026

Copy link
Copy Markdown
Owner

big refactor

a9lim added 5 commits April 25, 2026 22:14
…nd sdist

pyproject.toml had a hardcoded `version = "1.0.0"` plus an independent
`__version__ = "1.0.0"` in `src/rlaif/__init__.py`; two strings, one
will eventually drift. Hatchling reads `__version__` via AST without
importing the package at build time. The `build` job in
.github/workflows/ci.yml round-trips the resolved version against
`importlib.metadata.version()` to catch regressions before release.

Added a `py.typed` marker and the `Typing :: Typed` classifier so
downstream type checkers actually see rlaif as typed (pyright already
runs strict on `src/rlaif/`; we just hadn't been advertising it).

Hatchling's sdist defaults only ship pyproject + README + LICENSE plus
the package tree, so CONTRIBUTING.md, SECURITY.md, config.example.toml,
and tests/ were missing from the tarball; declared them in
`[tool.hatch.build.targets.sdist].include` so the sdist is
self-contained enough to run the suite from a tarball.

Switched to the SPDX `license = "AGPL-3.0-or-later"` form (PEP 639) and
dropped the now-redundant license classifier. Added `Changelog` and
`Documentation` URLs that PyPI's sidebar renders with icons.
Previous commit added the `[tool.ruff]` config and the dev-dep entry;
this wires ruff into the pre-commit suite (auto-fix on commit) and
applies the issues it surfaced on the existing tree:

- B904 in init.py: `raise SystemExit(130)` inside `except EOFError`
  was implicitly chaining the EOFError into the SystemExit's
  `__context__`. `raise ... from None` is what we actually want — the
  user typed Ctrl-D, that is not a bug worth showing them.
- UP035 in safety.py / server.py / snippet.py: `Callable` imported from
  `typing` is deprecated since 3.9; switched to `collections.abc`.
- UP037 in server.py: `Device.__init__`'s `pishock.PiShockAPI` /
  `HTTPShocker` annotations were string-quoted unnecessarily; the import
  is unconditional, the forward-reference dance was vestigial.
- I001 across init.py / safety.py / server.py / snippet.py /
  test_safety.py / test_server.py: ruff's import-sorter put stdlib /
  third-party / local in the conventional order.

Ruff's selected rule set is `E F W I UP B` — bug-finders plus import
sort and pyupgrade. Stricter than saklas/kenoma's `E F W` and
deliberately so: rlaif's safety code benefits from the extra signal.
…ob and macOS

CI was a single ``check`` job that did typecheck + pytest + dry-run.
Split into ``lint`` (ruff), ``typecheck`` (pyright strict on
src/rlaif/), ``test`` (matrix on python 3.11/3.12/3.13 + macos-latest
on 3.12), and ``build`` so failures land on the correct stage and run
in parallel. Top-level ``permissions: contents: read`` matches the
hardening pattern saklas and kenoma use.

The ``build`` job is the new robustness gate: it runs ``python -m
build`` against the dynamic-version setup, checks artifact metadata
with ``twine check``, installs the resulting wheel into a clean
environment, asserts ``rlaif.__version__ ==
importlib.metadata.version('rlaif')``, runs ``rlaif --version`` to
prove the console script is wired, then runs ``rlaif dry-run`` against
the installed wheel — catching packaging regressions where the wheel
is missing files needed by the safety layer.

macOS lands in the test matrix because rlaif's README documents
Windows-specific config-path behavior and macOS is the primary dev
target; running the full suite on macOS catches Path / line-ending
regressions before users hit them at ``rlaif init`` time.

The new release workflow mirrors the kenoma / saklas pattern:

1. Read ``__version__`` from src/rlaif/__init__.py via regex (no
   import; the heavy mcp / pishock paths don't run at release time).
2. Skip if the corresponding ``vX.Y.Z`` tag already exists.
3. Build, ``twine check``, install the built wheel, run ``rlaif
   --version``, run ``rlaif dry-run`` — the safety gate. Belt and
   suspenders against CI-on-source missing a packaging-only break.
4. Tag, push, publish to PyPI via Trusted Publishing (OIDC, no PyPI
   token), and emit a GitHub release with auto-generated notes.

PEP 740 attestations are enabled on the publish step (``attestations:
true``) so PyPI gets a sigstore-signed bundle along with the
artifacts. The workflow already has ``id-token: write`` for Trusted
Publishing; opting in to attestations is essentially free.

CI now also triggers on push to ``dev`` so feature branches get
visibility before opening a PR; release.yml stays scoped to
``push: main``.
… templates, CONTRIBUTING

- README gets PyPI version + monthly downloads badges to match the
  saklas / kenoma row (CI / PyPI / Downloads / License / Python).
- dependabot pins ``open-pull-requests-limit: 5`` per ecosystem and
  explicitly ignores ``pishock`` since CLAUDE.md documents the 1.2.1
  pin as deliberate; let dependabot stop fighting it.
- .editorconfig sets LF endings, trailing-whitespace trim, 4-space
  indent (2 for yml), and exempts Markdown's two-space line-break
  convention. Cross-editor consistency.
- PR template gains a ``ruff check`` checkbox and a release-bump
  callout reminding the contributor that touching ``__version__``
  triggers the publish workflow.
- CONTRIBUTING.md documents the ruff workflow, the new release flow,
  and the single-source-of-truth version rule (one literal in
  src/rlaif/__init__.py, hatchling reads it dynamically).
The matrix (3.11 / 3.12 / 3.13 on ubuntu plus macOS on 3.12) was
speculative robustness; 3.12 on ubuntu is the canonical CI target and
matches what saklas / kenoma run. Cross-version and cross-platform
breakage on a 1.3k-line MCP server doesn't justify the extra runners.

Branch protection's required-status-checks list is updated alongside
to drop the matrix entries.
@a9lim
a9lim merged commit e3b32d6 into main Apr 26, 2026
8 checks passed
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