Repository navigation
v0.114.0
The check system gains an observe-ability purity model backed by a written read-only-command standard, plus path-capable lint, format and type-check built-ins that replace the structured external-check adapter. Machine output on status, unreleased, check-name and monorepo graph/impact moves to strictcli's envelope, the scrub flow now requires safegit 0.27.0, and the test-suite and dev-status checks stop wiping and misreporting dev-sync overlays.
Context
The framework dependency moves onto released strictcli 0.40.0: the machine-mode
API this release is built on (ctx.json, ctx.payload, payload_schema and the
envelope) ships there, so the floor is raised to >=0.40.0 and the local
development overlay onto the strictcli checkout is retired. rlsbl now resolves
strictcli from PyPI like any consumer does.
The machine-output change is BREAKING for anything parsing rlsbl's --json.
rlsbl status --json, rlsbl unreleased --json, rlsbl check-name --json,
rlsbl monorepo graph --json and rlsbl monorepo impact --json no longer print
their own bare JSON document. Each now emits exactly one envelope whose
payload member carries what the command used to print at the top level, so a
consumer reads .payload where it previously read the document root. The same
move is why rlsbl release scrub requires safegit 0.27.0 or newer: it reads
safegit's --json through the envelope only, and older safegit does not emit
one.
The check-system work behind the headline is a redefinition rather than a new
feature bolted on. Purity now means "starts only allowlisted read-only
programs", which is a property the check itself can be audited against, so the
changelog validators, the two pre-push checks, workspace-unregistered and
go-companion-tags execute during --dry-run instead of reporting themselves
as would-run and checking nothing.
Breaking
- BREAKING:
external_checksentries withkind: "structured"are rejected. The tool-plus-paths shape is now the built-inlint/format/type-checkchecks configured under the top-levelcheckskey. The error names the replacing check and renders the migrated block. Freeform entries are unaffected. Separately,release run --dry-runin a repo with a customized pre-release hook now runs the preflight checks it can instead of listing every external check and executing none. - BREAKING:
--jsonoutput is now strictcli's envelope.status,unreleased,check-name,monorepo graphandmonorepo impactno longer print their own JSON document: machine mode emits exactly one envelope carrying the command's data underpayload, alongside the exit code, the structured preview and every diagnostic. Each command declares its payload's JSON Schema, whichrlsbl --dump-schemapublishes. Consumers read.payload; nothing else about the data changed.monorepo impactloses its--formatflag, andmonorepo graph's dropsjsonand now defaults totext. - BREAKING:
rlsbl release scrubnow requires safegit 0.27.0 or newer. safegit's--jsonmoved onto the strictcli framework's machine mode, where stdout carries exactly one document -- the envelope -- and safegit's own data is itspayloadmember. The scrub flow reads that shape only: the whole stream is parsed as one document (the partial decode that tolerated a trailing would-do log is gone), the data comes frompayload, and a scrub with nothing to rewrite is a null payload rather than empty output. An older safegit is refused by name, naming the version to install; there is no dual support and no fallback parse.
Features
- Shorter, more readable help for
rlsbl dev installandrlsbl monorepo rename-releasable. - A preview now validates your changelog.
rlsbl release run --dry-runused to list the changelog validators as "would run" and check nothing. They spawn only read-only git, so they are now classified pure and execute in a preview -- a broken commit hash, an uncovered commit or an orphaned entry is reported before you release rather than after. The same reclassification covers the two pre-push checks,workspace-unregisteredandgo-companion-tags. - New built-in checks:
lint,formatandtype-check. Each runs one Python tool (ruff / mypy) over a path list you declare in a top-levelchecksblock in.rlsbl/config.json, invoked through the project's own environment withuv run. Each is paired with a competing-scope guard that hard-errors when the tool's own config carries scope that would silently override or narrow those paths. An unconfigured check skips. - The sandboxed test runner honours
rlsbl dev syncoverlays. When a sibling checkout is overlaid onto a uv project's environment, the runner binds that checkout read-only into the sandbox and installs it editable offline, so the sandboxed suite tests the same source the bare suite does instead of the locked registry wheel. Repos with no overlay declared are unaffected, and every run prints which dependency source it used.
Fixes
- A failing linter no longer aborts the whole check run. An external check whose tool separates findings with blank lines (ruff, mypy) reported an internal
problem text must be a non-empty stringerror with no attribution instead of the tool's actual findings. Blank lines are now filtered before reporting, and an exception raised with no message no longer produces the same failure. gh auth tokenno longer runs anywhere. rlsbl used to ask gh to print a live GitHub credential to stdout and capture it, in three code paths (private-repo detection, GitHub topic tagging,rlsbl discover). Those now let gh apply the credential inside its own process (gh api), so no raw token ever transits an rlsbl pipe, buffer or log.rlsbl watchre-dispatches a failed run again. The auto-retry calledgh run rerun, which the effects layer refused because the command was misdeclaredread_only; the refusal was swallowed into "retry trigger failed" and the retry silently gave up.watchis now correctly declared mutating (it does not prompt), andgh run watchis an allowlisted read so a preview reports the real verdict.- The release CI gate reads check runs under
--dry-runagain. The paginatedgh apicall omitted--method GET, so it matched no allowlisted read and was recorded instead of performed -- the gate then parsed a placeholder where it expected JSON. config-schemaprobes the right directory. When a Go pipeline was missingartifact, the suggested value came from runninggo listin the process's current directory instead of the project root -- so in a monorepo, or from any subdirectory, the suggestion described the wrong project.dep-floorssees dev-group dependencies. Aninternal_dep_floorsentry whose dependency is declared in a PEP 735[dependency-groups]table was dropped silently -- the check produced no verdict for it at all, however far behind its declared floor was. Test-infrastructure dependencies live exactly there, so the check was inert for them.- The gh authentication check names its host.
rlsblnow runsgh auth status --hostname github.cominstead of the baregh auth status, and the observe allowlist is pinned to exactly that argv -- so no token-printing variant (--show-token,-t) can execute under--dry-runon the strength of an entry written for the token-free form. - Fix.
--jsononstatus,check-nameandunreleasedis now the framework-owned flag: it is recognised anywhere in the argument list rather than only after the command word, and its behaviour is otherwise unchanged. rlsbl dev statusno longer reports an installed overlay as missing. A uv workspace keeps one environment, at the workspace root, so an overlay installed for a member project read as[MISSING]anddev-overlay-driftfailed on a perfectly healthy environment. The environment is now resolved the way uv resolves it (workspace root,UV_PROJECT_ENVIRONMENT), and whether an install is editable is read from the PEP 610direct_url.jsonrecord throughimportlib.metadata-- never from the file layout, which an editable install does not populate with a package directory.- The test-suite check no longer uninstalls dev overlays.
rlsbl check-- and with it the release preflight and the pre-push hook -- ran a bareuv sync, which reinstalled the locked registry wheels over an activerlsbl dev syncoverlay without a word: the suite then tested released code, anddev-overlay-driftfailed on the wipe the check itself had caused. When the overlay declaration and the sentinel agree, the sync now carries--inexact --no-install-packageper overlay and the suite runs withuv run --no-sync(the shape the sandboxed runner already used), and a workspace sync excludes every member's overlaid packages. Files that disagree are a hard error naming both.