rlsbl v0.92.0 /Changelog
On this page

#Changelog

#0.92.0

Dispatch preid inputs, PR-mode resume fix, end-to-end pre-release integration test

#Features

  • Dispatch workflow. Release dispatch now supports all bump types (prerelease, hotfix) and pre-release identifiers (alpha, beta, rc, stable) as workflow_dispatch inputs.

#Fixes

  • PR-mode resume. PR-mode release resume now correctly preserves release_mode in the state file, preventing PR-mode releases from resuming as imperative.

#0.91.1

Fix critical pre-release wiring bugs and CI template pre-release awareness

#Fixes

  • Fix. preid now correctly wired through compute_release_version to bump_version. Pre-release versions (e.g., 0.43.0-alpha.0) are now produced correctly during releases.
  • Fix. CI publish templates now handle pre-release versions. npm templates add --tag {preid} for pre-releases. Docker template skips :latest tag for pre-releases.
  • Fix. Release group help text updated to list all 8 subcommands including resume and scrub.

#0.91.0

Pre-release channels, PR-based release flow, idempotent release resume, registry version detection, and remote release dispatch.

Context

This release adds three major capabilities: (1) pre-release channel support with PEP 440 translation and npm dist-tags, (2) PR-based release flow as an alternative to direct push, and (3) idempotent release resume for recovering from mid-release failures. Also adds registry version drift detection and a workflow_dispatch template for remote release triggers.

#Features

  • Idempotent release flow. New rlsbl release resume command. In-progress state file tracks completed steps; per-step guards enable safe resumption after mid-release failures.
  • Pre-release channel support. preid field in release TOML, bump = "prerelease" type, PEP 440 translation for PyPI, npm --tag dist-tags, Docker :latest skip, GitHub --prerelease flag, and changelog consolidation for stable releases.
  • PR-based release flow. release.mode = "pr" in config creates a release/vX.Y.Z branch and PR instead of pushing directly. Finalize workflow dispatches publish after merge. PR-mode undo closes the PR and deletes the release branch.
  • Registry version detection. rlsbl status --registry queries npm, PyPI, Go, and crates.io for published versions and shows drift between local and registry versions.
  • Remote release trigger. release-dispatch.yml scaffold template with workflow_dispatch inputs for --bump and --description.

#Fixes

  • Partial push rollback fix. Tag push failure no longer rolls back already-pushed commits.

#0.90.2

Fix test mocks for Python 3.14 compatibility

Context

ensure_github_topic and watch run_cmd migrated from run() to run_gh() but test mocks still targeted run(), causing failures on Python 3.14 CI

#Fixes

  • Bug fix. Fixed watch test mocks for run_gh migration in TestRePoll.

#0.90.1

Fix tagging test for Python 3.14 compatibility

Context

ensure_github_topic migrated from run() to run_gh() but the test mocks still targeted run()

#Fixes

  • Bug fix. Fixed test mock for run_gh migration in tagging module.

#0.90.0

Quick bump shortcut, run_gh centralization, changelog preflight unification

Context

Three major improvements in this release:

  1. Quick bump shortcut: rlsbl release run --bump patch --description "Fix X" allows simple releases without creating a release file first. The release file ceremony remains available for complex releases.
  1. run_gh centralization: All 33 repo-scoped gh CLI invocations now go through a single run_gh() function, replacing the old gh_env() pattern. This provides a cleaner API with consistent error handling and environment setup.
  1. Changelog preflight unification: Changelog validation is now unified into the preflight check system via app.run_checks(tag_expr="preflight-changelog"), eliminating duplicate validation logic between the release flow and the check system.

Also includes fixes for get_push_timeout crashing with config=None, uv.lock tracking, and a load_workspace scoping bug.

#Features

  • **New: run_gh() centralized GitHub CLI wrapper.** All 33 repo-scoped gh invocations now go through run_gh(), replacing the old gh_env() pattern with a cleaner API.
  • New: Changelog validation unified into preflight check system. app.run_checks(tag_expr="preflight-changelog") eliminates duplicate validation between release flow and check system.
  • New: Quick bump shortcut. rlsbl release run --bump patch --description "Fix X" bypasses the release file ceremony for simple releases.

#Fixes

  • Fix: get_push_timeout no longer crashes when config=None.
  • Fix: uv.lock is now tracked in git (was incorrectly gitignored).
  • Fix: load_workspace scoping bug in release flow — local imports no longer shadow module-level import.

#0.89.0

Preflight check integration and unreachable-code false positive fix

Context

Release flow now delegates test and lint validation to the check system via app.run_checks(tag_expr="preflight"), eliminating duplicate wrapper functions that historically diverged and caused release failures. Unreachable-code lint rule no longer treats inline comments as statements.

#Features

  • Release preflight checks via check system. The release flow now runs test-suite and library-lint checks via app.run_checks(tag_expr="preflight") instead of duplicate wrapper functions, with per-member iteration for releasable releases.

#Fixes

  • Unreachable-code false positive fix. Tree-sitter comment nodes are no longer treated as statements, fixing false positives and false negatives in the unreachable-code lint rule.

#0.88.1

Fix release lint to respect lint_allow from workspace.toml

#Fixes

  • Bug fix. Release lint now respects lint_allow from workspace.toml, matching the behavior of rlsbl check --tag quality.

#0.88.0

Configurable check timeout, centralized GitHub repo resolution with SSH alias support, push-access verification, library lint exceptions, and stderr surfacing for failed commands

Context

This release consolidates several reliability and usability improvements. The run_gh() migration replaces scattered remote-URL parsing across all commands with a single utility that handles SSH aliases and the github_repo config key. Push-access verification catches GH_TOKEN mismatches before the release flow runs. Library lint exceptions (lint_allow) support per-package overrides for forbidden-import checks. Configurable check timeout lets projects with slow test suites raise the default 120s limit.

#Features

  • Configurable check timeout. RLSBL_CHECK_TIMEOUT env var and check_timeout config key let you control test and lint timeouts (default remains 120s).
  • Centralized GitHub repo resolution. New github_repo config key and automatic SSH alias handling for all gh commands, replacing scattered remote-URL parsing with a single run_gh() utility.
  • Centralized GitHub repo resolution. Migrated yank, undo, release-retry, watch, PR, and check commands to run_gh().
  • Centralized GitHub repo resolution. Migrated checks, tagging, and private-repo detection to run_gh().
  • Push access verification. validate_gh_push_access checks the authenticated user has push access before releasing, with a hard error and actionable message on mismatch.
  • Library lint exceptions. lint_allow field in workspace.toml for per-package forbidden-import exceptions (e.g., allowing a library to import its own test utilities).

#Fixes

  • Stderr surfacing. Push and GitHub Release creation failures now show the actual error message from gh/git push instead of a generic failure.

#0.87.0

Ruff integration, unreachable-code detection, non-workspace test runner, and validate_release_targets union fix

Context

Added ruff as a dev dependency with ruff-lint quality check. Built custom unreachable-code detection in the Python AST linter using tree-sitter. Restructured the pypi test runner to probe where pytest is declared and build the correct uv run invocation per project (workspace member vs standalone). validate_release_targets now validates against the union of all releasable member targets. Removed silent error swallowing in member version sync and dead-code convention fallback.

#Features

  • New feature. Unreachable code detection in the Python AST linter -- flags code after unconditional return/raise and after exhaustive if/elif/else blocks.
  • New feature. detect_uv_workspace_root utility for detecting whether a project is a uv workspace member.
  • New feature. ruff-lint quality check runs ruff on the project during rlsbl check --tag quality. Skips gracefully when ruff is not installed.
  • New feature. Pypi test runner detects where pytest is declared per project (dependency groups, optional extras, uv dev deps) and builds the correct uv run invocation. Hard error when pytest is not declared. Workspace members preserve existing behavior.

#Fixes

  • Bug fix. Config read errors in member version sync now propagate to the release rollback handler instead of being silently skipped.
  • Bug fix. detect_python_package_root no longer returns a nonexistent convention path -- returns None when no package directory exists on disk.
  • Maintenance. Removed unused imports and variables across the codebase (ruff F401/F841 cleanup).
  • Bug fix. validate_release_targets now validates against the union of all releasable member targets, not just the representative member.

#0.86.0

AST-based __version__ bumping, dunder-version-missing check, and releasable test runner fix

Context

The __version__ bumping system was rewritten from regex to AST parsing, eliminating an entire class of missed version bumps (typed annotations, pre-release strings). A new dunder-version-missing check catches the pgdesign bug class where a version constant exists under the wrong name. detect_python_package_root gained uv build-backend and src/ layout support. The releasable test runner now dispatches the correct test command per member target type.

#Features

  • New feature. detect_python_package_root now supports uv build-backend module-root config, src/ layout filesystem detection, and raises a hard error on ambiguous package layouts.
  • New feature. __version__ bumping rewritten with AST parsing — now correctly handles typed annotations (__version__: str = "1.0.0") and pre-release version strings.
  • New feature. New dunder-version-missing project check detects pypi targets where __init__.py has a version-like constant (e.g., VERSION = "1.0.0") but no __version__.

#Fixes

  • Bug fix. Releasable test runner now detects the correct target type per member package instead of using the releasable-level registry for all members.
  • Bug fix. Member package version sync errors now propagate to the release rollback handler instead of being silently swallowed as warnings.

#0.85.0

Hotfix release type, TYPE_CHECKING import detection, ci-synced dev_node skip, root .rlsbl coexistence guard.

#Features

  • New feature. if TYPE_CHECKING: imports are now excluded from both deps-undeclared and deps-unused checks, eliminating false positives for typing-only imports.
  • New feature. bump = "hotfix" release type for infrastructure-only releases. Bypasses the user-facing entry requirement, generates a ### Hotfix changelog section from the release description, and errors if user-facing entries are present.
  • New feature. root-rlsbl-conflict check errors when both .rlsbl/ and .rlsbl-monorepo/ exist at the workspace root. Scaffold now skips entirely at workspace roots.

#Fixes

  • Fix. workspace-ci-synced check no longer fails for dev_node projects missing CI workflows.

#0.84.0

Go companion tags, workspace root CI fix, uvNoSources lint, BaseTarget fix.

#Features

  • New feature. Automatic Go companion tags during releasable releases. When a releasable contains non-private Go packages, {path}/v{version} tags are created alongside the primary releasable tag for Go module proxy compatibility.
  • New feature. Release rollback and release undo now clean up companion Go tags alongside the primary release tag.
  • New feature. go-companion-tags workspace check validates that Go releasable members have companion tags for the current version.

#Fixes

  • Fix. BaseTarget.template_vars() returns TemplateVars instead of plain dict, ensuring auto-namespacing works for all targets including those inheriting the base implementation.
  • Fix. {{#if uvNoSources}} conditional in pypi CI template now uses namespaced form {{#if pypi.uvNoSources}} for consistency with all other template conditionals.
  • Fix. Scaffold no longer generates CI workflows at monorepo workspace roots. The ci-router already handles per-package CI; root-level CI with import checks always failed.

#0.83.1

Fix release finalization leaving deleted unreleased.toml uncommitted.

#Fixes

  • Fix. Release finalization now properly commits the deletion of unreleased.toml after archiving, preventing a dirty working tree.

#0.83.0

Remove publish.json, releasable-owned targets, no empty release files, monorepo release subgroup.

Context

Breaking changes: publish.json config file removed (unused by all projects, 4-level inheritance simplified to 2-level). Release finalization no longer creates empty unreleased.toml. Monorepo release commands restructured into a subgroup (monorepo release -> monorepo release run, release-init -> release init, release-order -> release order). In explicit releasable mode, targets are releasable-owned and cannot be overridden by per-package config.

#Breaking

  • Breaking. Removed publish.json config file support. All config fields now live in config.json only. The 4-level inheritance chain is now 2-level (releasable config.json -> per-package config.json). The migrate-publish-config command is removed.
  • Breaking. Release finalization no longer creates an empty unreleased.toml. Run release init or monorepo release init to scaffold the next release file.
  • Breaking. Monorepo release commands restructured: monorepo release -> monorepo release run, monorepo release-init -> monorepo release init, monorepo release-order -> monorepo release order.

#Features

  • New feature. In explicit releasable mode, targets are owned by the releasable — per-package targets config cannot override the releasable's targets. Fixes release init failing to detect targets when members have targets: [].

#0.82.1

TemplateVars auto-namespacing, check-name polish, template fixes.

#Features

  • New feature. TemplateVars dict subclass auto-generates namespaced template variable keys, ensuring all scaffold modes (single-target, multi-target, monorepo sync) resolve variables consistently.

#Fixes

  • Fix. check-name --target github no longer shows redundant 'GitHub repos' in the Checked summary.
  • Fix. Monorepo check-names --target help text now includes github.

#0.82.0

Check system scope adapter, detect_targets config inheritance, template var hard errors, workspace-targets fix, check-name --target github, batch release bug fixes.

Context

Major architectural changes: declarative scope adapter for the check system (requires strictcli 0.21.0), detect_targets() now uses 4-level config inheritance with a two-tier rule (missing targets key is a hard error when config.json exists), and unresolved template variables are now hard errors instead of silent pass-through.

Breaking: projects with .rlsbl/config.json that lack an explicit "targets" key will now get a hard error with auto-detected hints. Template vars that previously survived as literal {{varName}} in output files will now error at scaffold/sync time.

#Breaking

  • Unresolved template variables are now hard errors. Scaffold and sync operations raise ConfigError instead of emitting a warning when template variables cannot be resolved. Namespace mismatches in cargo/go/npm templates fixed; optional variables wrapped in {{#if}} blocks.

#Features

  • Release init warning for explicit-mode monorepos. release init now warns when run in a monorepo with [[releasables]], directing users to monorepo release-init instead.
  • **check-name --target github support.** GitHub is now a first-class target for name availability checks, showing repo count and org-scoped availability.
  • **detect_targets config inheritance with two-tier rule.** Target detection now supports 4-level config precedence via read_project_config (releasable config dir for monorepo inheritance). Two-tier rule: no config.json means auto-detect from manifests; config exists without targets key raises ConfigError with hints.
  • Scope adapter for check system. Checks now declare scope tokens (e.g. workspace, non_dev_only, library) in checks.toml, and a scope adapter pre-filters context before check functions run. Removes isinstance boilerplate and inline filtering from all check implementations. Also adds a new scaffold-gitignore-stale check that warns when project .gitignore files are missing rlsbl-specific entries.

#Fixes

  • Batch release fix. Skip redundant environment validation (gh auth, clean tree, branch/remote checks) per sub-project in batch release mode -- the batch orchestrator already validates upfront.
  • **check-name no longer leaks GitHub API calls.** Previously, every npm/pypi/go name check also ran an unconditional GitHub lookup. GitHub checks now only run when --target github is specified.
  • **workspace-targets check improvements.** Skip dev_only and releasable=false projects in per-project target validation. Add union-per-releasable verification: each releasable must have at least one target across all its member packages.
  • Fix. sync_workspace skips uv sync when no pyproject.toml exists at workspace root, fixing pre-push failures in non-Python monorepos.

#0.81.7

Add 120s subprocess timeouts to Maven lint and all test runners

#Fixes

  • Add subprocess timeouts. Maven lint and all test runners now have 120-second timeouts, preventing the release pipeline from hanging indefinitely on slow or stuck subprocesses.

#0.81.6

Fix PyPI scanner false positives for prefixed package names

#Fixes

  • Fix PyPI scanner false positives. deps-undeclared no longer reports false positives when a workspace project's PyPI name differs from its workspace name (e.g., orxtra-transport vs transport).

#0.81.5

Fix CI: autouse saferm mock for scaffold tests

#Fixes

  • Fix CI test failures. Autouse saferm mock fixture applied to all scaffold tests.

#0.81.4

Fix CI: mock saferm in all scaffold tests

#Fixes

  • Fix CI test failures. All scaffold tests now mock saferm for CI environments.

#0.81.3

Fix CI: mock saferm in scaffold orphan tests

#Fixes

  • Fix CI test failure. Scaffold orphan detection tests now mock saferm for CI environments.

#0.81.2

Fix coverage check for releasable monorepos, Maven lint support, gradle lockfile sync, batch_limits inheritance

#Features

  • Maven lint support. lint_library() now runs detekt, checkstyle, or ./gradlew check for maven library projects via the new MavenLinter class.

#Fixes

  • Fix coverage check ignoring releasable JSONL entries. rlsbl check --tag changelog from the workspace root now correctly reads releasable-level changelogs instead of falling back to per-package paths. Also prevents crash on implicit-mode workspaces.
  • Fix gradle lockfile sync. Lockfile sync now checks for ./gradlew in the project directory instead of requiring gradle on PATH.
  • Batch limits inherit from releasable config. rlsbl changelog add now respects releasable-level batch_limits settings, and auto-created exclusions are written to releasable-level config when in releasable mode.
  • Fix phantom hashes.json entries. Scaffold no longer leaves stale entries in hashes.json for config files removed by the releasable config skip.

#0.81.1

Fix CI test failure: mock saferm in migration tests

#Fixes

  • Fix CI test failure. Migration tests now mock saferm for CI environments where it is not installed.

#0.81.0

Config-driven hooks, releasable config inheritance, Maven Central publishing, JVM monorepo support, Go strictcli detection, and migration CLI

Context

This release completes 9 phases of work spanning the full plan: release-blocking bug fixes (lockfile sync, changelog scope, selfdoc dirty tree), Go strictcli detection for 9 projects, releasable-level config inheritance with 4-source precedence, config-driven hooks replacing bash scripts (breaking), migration CLI for releasable model adoption, Maven Central publishing via the vanniktech plugin, JVM dependency graph and import scanning, Gradle version catalog support, and extended artifact cleanup.

Hook scripts are deprecated in favor of config entries. Existing customized scripts still work with a migration warning. New projects will not have hook scripts scaffolded.

#Breaking

  • Config-driven hooks replace bash scripts. Hook commands are now defined in config.json with dual syntax (string shorthand or structured objects with cmd/dir/env). Hook template scaffolding removed. Existing customized scripts still work with a migration warning.

#Features

  • Go strictcli detection. detect_strictcli() now finds Go projects using the strictcli library, scanning go.mod and entry points. Schema dump runs go run instead of uv run for Go projects.
  • Releasable-level config inheritance. Per-package config is now merged on top of releasable-level defaults at load time. Scaffold skips writing per-package config.json/publish.json when identical to the releasable config.
  • **rlsbl monorepo migrate-releasable command.** One-command migration to the releasable model: consolidates changelogs and versions, creates migration tags, cleans up per-package artifacts (hooks, bases, lint, CHANGELOG.md, version, redundant config).
  • Maven Central publishing support. New maven-central pipeline type delegating to the vanniktech Gradle plugin. Publish workflow template with GPG signing. POM metadata validation check. Maven test execution (./gradlew test / mvn test). CI templates updated to Java 25, setup-java@v5, setup-gradle@v6.
  • JVM monorepo support. Gradle/Maven dependency graph parsing for monorepo impact and release ordering. Java and Kotlin import scanning for dependency validation checks. read_metadata implemented for maven targets.
  • Gradle version catalog support. read_version/write_version work with libs.versions.toml via explicit version_catalog_key config. Build step (./gradlew build/mvn package), lint detection (detekt/checkstyle), and gradle.lockfile sync added for maven targets.

#Fixes

  • Workspace root lockfile sync. Release flow now syncs lockfiles at the workspace root for uv, npm, and Go workspaces after version bumps. Go workspace go.work.sum is handled separately with go work sync.
  • Fix multi-releasable changelog scope. Changelog validation in release flow now correctly scopes to the releasable's member projects instead of checking all commits in the repo.
  • Commit selfdoc outputs during release. Selfdoc-generated files are now committed immediately after selfdoc gen with an Autogenerated: true trailer, preventing dirty-tree failures on release retry.

#0.80.0

Batch release improvements: monorepo-wide lock, upfront validation, --watch support, dry-run summary

#Features

  • Batch monorepo-wide lock. rlsbl monorepo release acquires a workspace-level lock before the batch loop, preventing concurrent batch releases from interleaving.
  • Upfront validation for batch release. gh auth, clean tree, and branch checks run once before releasing any package, failing fast on misconfiguration.
  • **--watch/--no-watch for monorepo release.** Watches CI for the last release's commit after the entire batch completes. Per-package watch hints suppressed during batch.
  • Dry-run summary for batch release. Shows each releasable's bump type and description in release order.

#Fixes

  • **Fix: uv build --out-dir dist in publish template.** Ensures build artifacts land in the expected directory for PyPI upload.
  • Fix: shallow clone test failure in CI.

#0.79.2

Fix migration consolidation bugs, CI template variable, and shallow clone test failure

#Fixes

  • Fix: migration consolidation bugs. consolidate_changelogs() now deduplicates cross-package entries, auto-creates batch exclusions for oversized entries, and creates a consolidation tag to prevent scope expansion failures.
  • **Fix: unreplaced minRequiredPython in CI template comment.** Template now uses un-namespaced variable name that works in both single and multi-target scaffold.
  • Fix: status command test failure in CI shallow clones.

#0.79.1

Raise CI coverage threshold to 90% with 4873 tests at 91.78% coverage

#Features

  • CI coverage threshold raised to 90%. Test suite expanded to 4873 tests with 91.78% coverage.

#0.79.0

Fix publish workflow releasable tags, UV_NO_SOURCES for monorepos, namespace package scanning

Context

Three gaps discovered during first real-world use of the releasable model: (1) publish workflow ignored releasable tags, (2) UV_NO_SOURCES broke monorepo CI for workspace-source projects, (3) deps-unused produced false positives for namespace packages. Also adds template engine conditionals, extract/absorb CLI commands, migrate-publish-config command, and removes implicit releasable mode (monorepos must define [[releasables]]).

#Breaking

  • Remove implicit releasable mode. Monorepo workspaces must define [[releasables]] in workspace.toml. Hard error if missing.

#Features

  • Template engine conditionals. {{#if varName}}...{{/if}} blocks for conditional template content.
  • **New command: rlsbl migrate-publish-config.** Splits publishing fields from .rlsbl/config.json into .rlsbl/publish.json.
  • **New commands: rlsbl monorepo extract, absorb, extract-releasable.** First-class operations for moving packages in and out of monorepos.

#Fixes

  • Fix: publish workflow releasable tags. Monorepo publish router uses releasable tag prefixes instead of per-project tags in explicit mode.
  • Fix: UV_NO_SOURCES omitted for monorepo members. CI template conditionally includes UV_NO_SOURCES only for projects with path-based sources. Monorepo sync strips it as a safety net.
  • Fix: namespace package import scanning. deps-unused correctly detects workspace imports through namespace packages (e.g., from orxt.protocols import X). Auto-discovers namespace-to-project mapping from source layout.

#0.78.0

Releasable model: groups of packages sharing a version, changelog, and release lifecycle

Context

Introduces the releasable model — a ground-up redesign of monorepo versioning. Instead of per-package versioning (N versions, N changelogs, N tags), packages can be grouped into releasables that share a single version, changelog, and release lifecycle. The model covers the full stack: data model, version management, changelog scoping, release flow, hooks, scaffold, migration tooling, extract/absorb operations, and single-project unification.

Breaking: dev_node is split into dev_only (boundary guardrail) and releasable = false (not versioned). The --dev-node CLI flag is renamed to --dev-only. The dev-node-boundary check is renamed to dev-only-boundary.

#Breaking

  • dev_node split. dev_node is now two independent concepts: dev_only (boundary guardrail preventing runtime dependencies) and releasable = false (not versioned). The --dev-node CLI flag is renamed to --dev-only. The dev-node-boundary check is renamed to dev-only-boundary.

#Features

  • Releasable model. Packages can be grouped into releasables sharing a version, changelog, and release lifecycle. Define [[releasables]] in workspace.toml and assign packages with releasable = "name" or releasable = false.
  • Per-releasable version files. In explicit mode, each releasable stores its version at .rlsbl-monorepo/releasables/{name}/version. Version consistency checks treat this as the source of truth.
  • Per-releasable changelog. In explicit mode, changelogs live at .rlsbl-monorepo/releasables/{name}/changes/. Commit coverage, validation, and CHANGELOG.md generation are scoped to releasables. Entries gain an optional packages field for per-package attribution.
  • Publishing config separation. Publishing-related fields (targets, private, pipelines, push_timeout, tag) can now live in .rlsbl/publish.json separate from .rlsbl/config.json. Hard error if both files have publishing fields.
  • Release flow on releasables. rlsbl release run creates one commit and one tag per releasable. Batch release iterates releasables in dependency order. Release file supports [releasables.name] sections. Undo, retry, yank, and edit commands adapted.
  • Per-releasable hooks. Two-level hook system: per-releasable hooks at .rlsbl-monorepo/releasables/{name}/hooks/ plus per-package hooks. Tests and lint aggregate across all member packages.
  • Per-package cleanup utilities. cleanup_per_package_release_state() removes dead .rlsbl/changes/ and .rlsbl/releases/ for releasable members. verify_minimal_rlsbl() checks for unexpected files.
  • Scaffold releasable directories. In explicit mode, rlsbl scaffold and rlsbl monorepo sync create per-releasable directory structure. Per-package changelog infrastructure is skipped for releasable members. monorepo add gains --releasable flag.
  • Migration tooling. detect_migration_state() analyzes workspace readiness. consolidate_changelogs() merges per-package changelogs into per-releasable. consolidate_versions() unifies versions. create_migration_tag() creates releasable-format tags.
  • Standalone releasable model. Single-project repos internally use the releasable abstraction. Optional .rlsbl/releasable.toml for explicit configuration.
  • Extract and absorb. cmd_extract() extracts a package or releasable from a monorepo into a new repo via git filter-repo. cmd_absorb() brings an external repo into a monorepo via git subtree add. Changelog migration included.

#Fixes

  • Audit fixes. Release checks use releasable tag format. Prepush checks are releasable-aware. Post-release hooks use multi-level system. Publishing config conflict detection handles edge cases.

#0.77.1

Fix stale commit-level batch exclusion cleanup

Context

clean_stale_exclusions now removes commit-level batch exclusions when all referenced commits have been finalized, matching the existing entry-level cleanup behavior.

#Fixes

  • Bug fix. Stale commit-level batch exclusions are now cleaned from config.json during release finalization, matching the existing cleanup for entry-level exclusions.

#0.77.0

GitError/PostReleaseError exceptions, detached HEAD/shallow clone/push timeout handling, variant delay, dep_validation realpath

Context

Final cleanup round: completed the exception hierarchy (GitError for git infrastructure, PostReleaseError for post-mutation failures), fixed three unhandled edge cases (detached HEAD, shallow clone, push timeout), added rate-limiting delay to variant checks, standardized dep_validation.py on realpath, and triaged the hardening roadmap into focused todos.

#Breaking

  • Breaking. Added GitError and PostReleaseError exception types. Last 2 sys.exit calls in execute.py converted to PostReleaseError.

#Features

  • New feature. check-name variant checks now respect the --delay flag for rate-limiting, using sequential checking instead of concurrent threads when a delay is set.

#Fixes

  • Bug fix. Detached HEAD now raises a clear GitError instead of silently returning "HEAD" as the branch name, which caused dangerous behavior in push_if_needed and release undo.
  • Bug fix. Shallow clones now produce a clear GitError instead of silently falling back to all-history range. Consolidated duplicate tag discovery functions into a single get_last_version_tag() in utils.py.
  • Bug fix. Push timeout now raises GitError with an actionable message instead of a raw Python traceback.
  • Bug fix. Standardized dep_validation.py path normalization on realpath, consistent with the rest of the codebase. Fixes potential mismatches with symlinked project directories.

#0.76.0

Split release.py into a package, ExemptionRegistry, path normalization, orphan messaging

Context

The 1985-line release.py monolith was split into 6 modules with clean boundaries. 27 sys.exit calls converted to a proper exception hierarchy. The 24-parameter _run_release_mutating signature replaced with a ReleaseState dataclass. Changelog exemptions centralized into an ExemptionRegistry. Path normalization standardized on realpath. Orphan check messaging improved with entry context.

#Breaking

  • Breaking. Split release.py (1985 lines) into a 6-module release/ package: __init__.py (orchestrator), execute.py, validate.py, hooks.py, publish.py, rollback.py. Replaced the 24-parameter _run_release_mutating signature with a ReleaseState dataclass. Converted 27 sys.exit calls to ReleaseValidationError/HookError exceptions.

#Features

  • New feature. Centralized changelog exemption logic into ExemptionRegistry with ordered predicates and per-rule unit tests. Fixed batch exclusion hash matching (abbreviated hashes now resolve to full SHAs).

#Fixes

  • Bug fix. Changelog orphan check now reports entry context (file, line, how many commits are valid) instead of bare hash errors. Detects partially stale entries where all commits are either unresolvable or out of range.
  • Bug fix. Standardized path normalization on realpath across root discovery, containment checks, and lint exclusion. Fixes potential mismatches when project directories are accessed through symlinks.

#0.75.1

Fix workspace test runner uv sync

Context

The workspace test runner was running uv sync per sub-project instead of once at the workspace root, breaking monorepos with cross-project dependencies.

#Fixes

  • Bug fix. Workspace test runner now runs uv sync --all-packages at the workspace root instead of per sub-project, fixing monorepo test suites with cross-project dependencies.

#0.75.0

Normalization collision detection, ultranorm by default, claim-name command, exit codes

Context

check-name was reporting names as available when registries would reject them due to normalization collisions (e.g., llmloop vs llm-loop on PyPI, toolstream vs tool-stream on npm). This release fixes the false positives, adds the claim-name command for definitive name reservation, and introduces proper exit codes.

#Breaking

  • Breaking. Removed _normalize_npm_moniker internal function (replaced by normalize_npm from targets/utils). Removed the --ultranormalized-variants flag (ultranorm is now always-on for PyPI).

#Features

  • New feature. check-name now detects normalization collisions as hard errors. Names like llmloop that collide with llm-loop on PyPI, or toolstream that collides with tool-stream on npm, are correctly reported as taken instead of a soft warning.
  • New feature. Ultranormalization (visual-ambiguity detection like c1i/cli) now runs by default for PyPI. The dead --ultranormalized-variants flag and its misleading tip have been removed.
  • New feature. check-name exit codes now distinguish results: 0 for available, 1 for taken/collision, 2 for error.
  • New command. rlsbl claim-name <name> --target npm|pypi publishes a minimal placeholder package to definitively reserve a name on a registry.

#Fixes

  • Bug fix. check-name npm moniker search failure is now a hard error instead of silently reporting the name as available.

#0.74.1

Fix first release on empty remote

Context

When a project had a configured remote but no commits had been pushed yet, the remote-ahead check would abort because origin/{branch} did not exist. The check now detects this and skips gracefully.

#Fixes

  • Bug fix. Release no longer aborts on first push to an empty remote. When origin/{branch} does not exist after a successful fetch, the remote-ahead check is skipped with an informational message instead of hard-aborting.

#0.74.0

Blog post integration for releases, richer hook environment variables, and assembly support in post-release hooks.

Context

Adds blog = true support in release TOML to auto-generate blog posts via selfdoc during releases. Enriches hook env vars with bump type, previous version, and description. Adds conditional selfdoc assembly push to the post-release hook template for unified documentation deployment.

#Features

  • Blog post integration. New blog = true field in release TOML generates a blog post during release via selfdoc post generate --from-release. Supports user-authored body file, changelog integration, and archival.
  • Richer hook environment. Pre-checks, pre-release, and post-release hooks now receive RLSBL_BUMP_TYPE, RLSBL_PREV_VERSION, and RLSBL_DESCRIPTION environment variables.
  • Assembly support in post-release hooks. Post-release hook template now conditionally runs selfdoc assembly push when assembly config is present.

#0.73.0

Changelog edit command, dev_node release prohibition, config hardening, and coverage reporting

#Breaking

  • Breaking. Dev node projects can no longer be released. rlsbl release run and rlsbl release edit now error with "dev_node projects cannot be released". Remove dev_node = true from workspace.toml to make a project releasable.

#Features

  • New command. rlsbl changelog edit amends entries in released (read-only) JSONL files -- temporarily unlocks the file, appends the entry, re-locks, regenerates CHANGELOG.md, and syncs GitHub Release notes.
  • New. CI now reports test coverage via pytest-cov.

#Fixes

  • Fix. The private config key is now required -- missing or corrupted config files produce a hard error instead of silently continuing.
  • Fix. Retry gh release create with race-condition detection when the release already exists.

#0.72.0

Silent exception audit, release robustness fixes, dev-node batch guard

Context

Systematic audit replaced silent exception swallowing with explicit warnings or hard errors across all commands. Release undo and create now handle GitHub API failures gracefully. Dev-node projects in batch releases now hard-error instead of silently skipping.

#Breaking

  • Dev-node batch release guard. rlsbl monorepo release now hard-errors if a dev_node project is included in a batch release, instead of silently skipping it.

#Fixes

  • Silent exception audit. Replaced silent exception swallowing across all commands with explicit warnings or hard errors. Safety guardrails now fail loudly instead of silently bypassing checks.
  • Fix CheckResult status. Use 'fail' instead of 'error' to comply with strictcli constraints.
  • Graceful release failure handling. rlsbl release run now handles gh release create failures gracefully instead of crashing.
  • Undo pre-check. rlsbl release undo now checks that the GitHub Release exists before attempting to delete it.

#0.71.1

Release undo traceback logging, per-version .md canonical regeneration, test isolation fixes, and CI JUnit XML reporting.

#Fixes

  • Fix. release undo error handlers now log tracebacks instead of silently swallowing exceptions.
  • Fix. Per-version .md files are now regenerated from the archived release .toml after finalization, ensuring metadata is sourced from the canonical file.

#0.71.0

Scaffold-conflict check consolidation, scope-aware deps-unused, release finalization fixes, and dev_node layer exemption.

Context

Post-0.70.0 cleanup wave driven by loose ends from the previous session plus cross-session review. The two overlapping scaffold-conflict checks merged into one (paired-marker detection, recursive .rlsbl/ scan, path:line reporting). deps-unused became scope-aware: guarded imports satisfy only optional deps, so a hard dependency imported only inside try/except ImportError is now flagged. Release finalization gained two fixes: backfilled per-version .md files are committed (no more dirty tree after release) and the new version's .md gets description/context from day one. Layers auto-exempt dev_node projects. All 14 selfdoc SEO warnings eliminated. test_check.py migrated off unittest.TestCase.

#Breaking

  • Check consolidation. The scaffold-conflict-markers check is removed; scaffold-conflicts absorbs it: it now scans all of .rlsbl/ recursively, reports each conflicted file as path:line, and no longer false-positives on bare ======= lines (e.g. markdown setext underlines).

#Features

  • Custom asset build commands are now echoed to stdout before execution, providing an audit trail of the exact shell command run during release asset builds.
  • New check. scaffold-conflicts errors when scaffold-managed files or CI workflows contain unresolved merge conflict markers, blocking releases until resolved.

#Fixes

  • Fix. release run no longer errors when push_timeout is unset; it defaults to 120 seconds as documented.
  • Fix. release run re-run after a partial failure could silently overwrite an already-finalized changelog file; it now aborts with a clear error.
  • Fix. Advisory lock files (.rlsbl/lock) are now gitignored by scaffold, so a crashed release can no longer dirty the working tree.
  • Fix. release undo left the release file finalized: the bump type, description, and context vanished from unreleased.toml and a stale read-only vX.Y.Z.toml remained; undo now restores it (preserving any new user content with a warning).
  • Fix. Releases no longer leave a dirty working tree: backfilled older per-version changelog .md files are now included in the finalization commit, and the new version's .md now contains the release description and context.
  • deps-unused is now scope-aware. Imports inside try/except ImportError only satisfy optional deps (scope dev/peer); a hard dependency (runtime/explicit) imported only inside a guard is flagged with a dedicated error suggesting to declare it optional or import it unconditionally.
  • Fix. get_push_timeout now raises ConfigError instead of ValueError for invalid RLSBL_PUSH_TIMEOUT or push_timeout config values.
  • Fix. The layers-violations check now auto-exempts dev_node projects; they no longer need manual layer assignments.
  • Fix. rlsbl deploy --dry-run now displays local_steps before remote steps, mirroring execution order.
  • Docs. Fixed stale references to the old monolithic checks.py after the split into the checks/ package.

#0.70.0

Custom exception hierarchy, checks.py modularization, import scanning fixes, deploy local_steps, and 9 truncation removals.

Context

Codebase investigation surfaced 50 curiosities; 13 were elevated to decisions and executed across 11 phases. The biggest structural changes: 105 bare ValueErrors replaced with 5 typed exception classes, and the 1,978-line checks.py split into a 6-module package. Import scanning got two correctness fixes (guarded imports for deps-unused, root-relative test context detection). The deploy module gained local_steps for pre-SSH commands like cross-compilation. All silent truncation was purged (9 instances). Test suite gained xdist (96s -> 27s), parametrization, and real CI runs.

#Breaking

  • Custom exception hierarchy replaces ValueError. rlsbl now raises ConfigError, WorkspaceError, ChangelogError, VersionError, and ReleaseFileError instead of bare ValueError. Code that catches ValueError from rlsbl APIs must update to catch the new types.
  • Ultranorm variant cap is now a hard error. check-name with highly-ambiguous names now errors instead of silently warning and continuing with incomplete results.

#Features

  • npm CI templates handle missing lockfiles. Templates now use npm ci when a lockfile exists and fall back to npm install when absent. Zero-dependency wrapper packages are auto-detected and skip CI generation.
  • npm wrapper improvements. bin/cli.js now verifies Python >= 3.11, checks rlsbl is installed (with clear error messages), and supports Windows via python3/python/py fallback.
  • Deploy: local_steps field. Deploy targets can now run local commands (cross-compilation, file transfers) before SSH-based remote steps.
  • target-count selfdoc directive. New directive dynamically generates the release target count with a link to the targets documentation page.

#Fixes

  • Remove silent data truncation. Changelog commit messages and batch exclusion reasons are no longer silently truncated at 72/60 characters.
  • Remove display truncation caps. Unreleased subjects, pre-push missing commits, OTA native files, orphan hashes, and discover descriptions now show full content instead of capping at arbitrary limits.
  • Changelog regeneration preserves release metadata. Descriptions and context from archived release .toml files are now read during CHANGELOG.md regeneration, fixing data loss on subsequent regenerations.
  • deps-unused no longer flags guarded imports. Imports inside try/except ImportError blocks now count as used, fixing false positives for optional dependencies.
  • Test context detection uses root-relative matching. src/test/ is no longer falsely classified as test code. Added testdata/ and integration_test/ patterns.
  • BFS and topological sort use correct data structures. Workspace graph BFS uses deque (O(1) dequeue) and topological sort uses heapq instead of re-sorting.
  • Spec docs corrected. Fixed incorrect claim that spec target has no ci_templates.
  • Deploy docs corrected. Fixed config key from deploy_targets to deploy.

#0.69.2

Deno publish idempotency, orphan sweep script

#Features

  • Feature. Deno publish template is now idempotent with JSR version-exists pre-check.

#0.69.1

Scrub tag matching, cmd_amend fix, strictcli public API, todo cleanup

#Fixes

  • Fix. Release scrub correctly identifies which project a monorepo tag belongs to using prefix matching instead of version-only lookup. Also caches workspace loading (5 calls reduced to 1).
  • Fix. changelog amend uses writable_jsonl context manager, preventing file permission leak if duplicate commit check exits early.

#0.69.0

Managed-files registry, lint config filtering, publish idempotency, monorepo path exemption

#Features

  • Feature. Scaffold now tracks generated files in .rlsbl/managed-files.json and automatically deletes orphans on re-scaffold. Hash comparison protects user-modified files. Separate from hashes.json (change detection).
  • Feature. Scaffold only generates lint configs for declared targets (pypi→python.toml, npm→npm.toml, go→go.toml). Unused configs are orphan-detected on next scaffold.
  • Feature. All publish workflow templates are now idempotent (safe to retry). PyPI uses skip-existing, npm/cargo/hex use version-exists pre-checks.

#Fixes

  • Fix. .rlsbl-monorepo/ paths are now auto-exempted from changelog coverage requirements.

#0.68.4

scaffold --force preserves gitignore entries

#Fixes

  • Fix. scaffold --force no longer destroys user-added .gitignore entries. The additive merge (only add, never remove) now applies regardless of --force.

#0.68.3

CI template UV_NO_SOURCES fix

#Fixes

  • Fix. CI template sets UV_NO_SOURCES=1 env var at workflow level, covering both uv sync and uv run commands.

#0.68.2

CI uses --no-sources for portable uv sync

#Fixes

  • Fix. CI template uses uv sync --no-sources to ignore local path overrides and resolve from PyPI in CI. Works correctly in both standalone projects and monorepo workspaces.
  • Fix. test-suite check skips gracefully at workspace root instead of hard-erroring.

#0.68.1

Per-target CI files, YAML indent fix, monorepo sync update

#Features

  • Feature. Multi-target projects now generate per-target CI workflow files (ci-pypi.yml, ci-go.yml, etc.) instead of a single ci.yml from the primary target. npm wrapper packages (no test script) skip CI generation entirely. Old ci.yml is automatically cleaned up on re-scaffold.
  • Feature. Monorepo sync handles per-target CI files: globs ci-*.yml from sub-projects, syncs each with project-name prefix, cleans up stale files.

#0.68.0

release scrub command, V4 hook removal

#Breaking

  • Breaking. Removed pre-push-check command. Run rlsbl scaffold to upgrade your hook to the current format (rlsbl check --tag prepush).

#Features

  • Feature. New rlsbl release scrub command wraps safegit scrub with automatic release metadata cleanup: remaps JSONL changelog hashes, regenerates CHANGELOG.md, force-pushes rewritten history, and recreates GitHub Releases for affected tags. Includes error recovery via scrub-result.json.

#Fixes

  • Fix. Merged publish.yml now uses correct 6-space indentation for GitHub Actions steps, matching the standard 2-space-per-level convention. Previously, multi-pipeline projects got 4-space indentation due to missing ruamel.yaml indent configuration.

#0.67.1

V4 shim workspace fix, check-name multi-target, zero SEO warnings

#Features

  • Feature. Comprehensive documentation update: rewrote pre-push hook section, added test-suite-workspace docs, monorepo pre-push behavior, deps-unused note, and eliminated all SEO warnings (was 104, now 0).

#Fixes

  • Fix. Deprecated pre-push hook (old format) now creates proper workspace context at monorepo root, enabling all prepush checks including test-suite-workspace.
  • Fix. check-name --target now supports multiple values. Passing --target npm --target pypi checks both registries instead of silently ignoring the first. Invalid target names produce a hard error.

#0.67.0

Monorepo pre-push support, test-suite-workspace check, release rollback cleanup

#Features

  • Feature. New test-suite-workspace check runs tests for affected workspace projects during pre-push. Detects changed files from push refs, maps to projects via watch patterns, skips dev_node projects.

#Fixes

  • Fix. Pre-push hook now works from monorepo root directory. test-suite check hard-errors in workspace context with a clear message directing to test-suite-workspace.
  • Fix. Release rollback now cleans up orphaned generated files (versioned JSONL, markdown, release TOML) that previously blocked retry with 'working tree not clean'.

#0.66.4

Dynamic check-count directive, quality count fix, exclusion cleanup integration test

#Features

  • Feature. New check-count selfdoc directive auto-generates the check count from checks.toml, eliminating manual count maintenance in docs.

#0.66.3

deps-undeclared respects try/except ImportError for optional imports

#Fixes

  • Fix. deps-undeclared check no longer flags imports inside try/except ImportError or try/except ModuleNotFoundError blocks. These are standard Python optional-dependency patterns and are now correctly recognized as intentionally unguarded.

#0.66.2

Auto-cleanup stale exclusions, DRY refactor manual-warning, hook V5 e2e test

#Features

  • Feature. Stale batch_limits exclusions (referencing version: unreleased) are automatically removed from config.json during release finalization.

#0.66.1

Fix uv sync stripping pytest in workspaces, add workspace-unbuildable check

#Features

  • Feature. New workspace-unbuildable check detects workspace members with broken build configs before uv sync --all-packages fails at release time.

#Fixes

  • Fix. uv sync now uses --all-packages to prevent stripping pytest from workspace member venvs. Fixes test runner falling through to system Python in uv workspaces.

#0.66.0

Prepush check system: test-suite check, version-tag skip removal, hook V5

Context

Major overhaul of the pre-push hook system. All pre-push logic migrated into the rlsbl check system under a new 'prepush' tag. The hook now runs 'rlsbl check --tag prepush' with 4 checks (changelog coverage, gitignore guard, manual-push warning, test-suite). Version-tag skip removed -- checks always run. Shared testing.py module extracted from release flow.

#Features

  • Feature. New prepush check tag with 4 checks: prepush-changelog-coverage, prepush-gitignore-guard, prepush-manual-warning, and test-suite. Pre-push hook now runs rlsbl check --tag prepush instead of the deprecated rlsbl pre-push-check. Version-tag skip removed -- all checks always run. Fast-fail ordering via depends_on: test-suite skips if changelog coverage fails.
  • Feature. Extracted shared test-running logic to rlsbl/testing.py. Release flow and test-suite check both use the same function, eliminating duplication.
  • Feature. Updated documentation for prepush check system, fixed stale check counts.

#0.65.4

Fix CI test failure from --yes flag in safegit commit calls

#Fixes

  • Fix. Updated commit command tests to expect the new --yes flag in safegit calls.

#0.65.3

safegit --yes, doc gaps, SEO fixes, retry dedup test

#Features

  • Feature. Passes --yes to safegit commit calls, future-proofing against interactive prompts in safegit.
  • Feature. Documentation expanded: glob pattern reference for layers, user-level config docs, flag-to-config mapping table, enriched module docstrings for SEO, and expanded section intros across 5 pages.
  • Feature. Added concurrent retry deduplication test verifying only one retry fires per workflow name when multiple runs fail in parallel.

#0.65.2

Watch retry dedup, no-runs exit 0, docs polish

#Features

  • Feature. Documentation expanded: new utility commands guide, fixed pipeline per-type inaccuracies, added Flutter release config and deploy env var expansion docs, improved section intros for AI citation.

#Fixes

  • Fix. Watch auto-retry now deduplicates by workflow name, preventing multiple retries when parallel runs from the same workflow fail. Watch exits 0 (not 1) when no CI runs are found, since the release already succeeded.

#0.65.1

Fix CI test failure from batch hint message

#Fixes

  • Fix. Batch size check test updated to account for hint message in failure details.

#0.65.0

Documentation overhaul and notification UX fix

Context

Comprehensive docs rewrite (13 new guide pages, 2600+ lines), notification click-to-open fix, pipeline env var validation ordering fix, and new --allow-batch flag for changelog add.

#Features

  • Feature. Comprehensive documentation overhaul: 13 new guide pages covering release workflow, changelog, scaffold, checks, deploy, dev workflow, import scanning, dependency validation, pipelines, layers, and native targets. Expanded targets, monorepo, and configuration references. Fixed stale check counts.
  • Feature. changelog add --allow-batch flag auto-creates a batch_limits exclusion when an entry exceeds the commit limit, preventing agents from splitting cohesive entries. Batch size check now runs at add-time (not just during release validation).

#Fixes

  • Fix. Desktop notification no longer auto-opens browser unconditionally; URL opens only when the user clicks the notification action button.
  • Fix. Local pipeline env var validation now runs before mutating operations, preventing partial state on missing credentials.

#0.64.2

Fix Docker metadata false positive in scaffold check, add SSH host validation for subtree remotes.

#Features

  • New feature. Validate that subtree remote SSH hosts match the origin remote host, catching misconfigured mirror URLs early.

#Fixes

  • Fix. Exclude Docker metadata-action type=semver,pattern= lines from the scaffold-unreplaced-vars check. These lines use {{version}}, {{major}}, {{minor}}, and {{patch}} as Docker's own template syntax, not unreplaced rlsbl variables.

#0.64.1

Fix dead-modules false positives and watch test notification leak.

#Features

  • New. Auto-retry failed CI workflows once before reporting failure.
  • New. Open GitHub Actions page on CI failure and Release page on success when watch notifications fire.

#Fixes

  • Fix. Exclude .selfdoc, _build, and browser asset directories from dead-modules scan to prevent false positives.
  • Fix. Mock notifications and URL opens in watch tests to prevent desktop notification spam during test runs.

#0.64.0

Monorepo mirror command, native-android and native-ios targets.

#Features

  • New command. monorepo mirror copies monorepo sub-project state (version, changelog, docs) into a standalone mirror repository for independent distribution.
  • New target. native-android release target for Android application projects using Gradle, with automatic mutual exclusion against the maven target to prevent conflicts.
  • New target. native-ios release target for iOS application projects with Xcode and Tuist support.

#0.63.2

Fix CI test failure when selfdoc not installed.

#Fixes

  • Fix. CI test no longer fails when selfdoc is not installed in the test environment.

#0.63.1

Pass RLSBL_DIST_DIR env var to custom_assets build commands.

#Features

  • New feature. Custom asset build commands now receive the dist directory via the RLSBL_DIST_DIR environment variable, eliminating the need for hardcoded paths.

#0.63.0

Pipeline separation: versioning and publishing are now independent concerns.

Context

Breaking: publish() and build_assets() removed from targets, replaced by pipeline types. DocsTarget removed (use cloudflare-pages pipeline). flutter-ios/flutter-android merged into single flutter target. The publish config key is no longer recognized -- use pipelines. New: 9 built-in pipeline types, custom_assets, hooks override built-ins, 5 new checks, pipeline introspect table. Fix: multi-target array bugs in snapshot/graph/status.

#Breaking

  • Pipeline system replaces target.publish(). The publish config key is no longer recognized; use pipelines instead. BaseTarget no longer has publish() or build_assets() methods.
  • DocsTarget removed. Docs deployment is now a cloudflare-pages pipeline, not a target.
  • Flutter targets merged. flutter-ios and flutter-android merged into a single flutter target.

#Features

  • Pipeline infrastructure. 9 built-in pipeline types: npm, pypi, go, cargo, deno, hex, maven, docker, cloudflare-pages.
  • custom_assets support. Arbitrary artifact builds via pipeline config.
  • Hooks override built-ins. Customized pre-release hooks skip built-in tests/lint.
  • 5 new checks. private-publish-workflow, scaffold-conflict-markers, npm-private-mismatch, target-version-readable, selfdoc-version-drift.
  • Pipeline introspect table. Shows registered pipeline types in selfdoc output.

#Fixes

  • Multi-target bug fixes. Fixed snapshot, graph, and status commands to handle multi-target projects instead of taking only the first target.

#0.62.0

Capability-gated publish/build_assets, Swift inheritance cleanup, version_file dir_path, and bug fixes.

Context

Breaking: BaseTarget.build_assets() returns [] instead of raising NotImplementedError. publish() and build_assets() calls are now gated on target.capabilities. SwiftAppleTarget inherits from SwiftTarget. version_file() accepts optional dir_path for dynamic filename resolution. Plain exclusion list fixed. Flutter table cells corrected.

#Breaking

  • Breaking. BaseTarget.build_assets() returns an empty list instead of raising NotImplementedError. Custom targets that relied on the exception should declare build_assets in their capabilities frozenset.

#Features

  • Refactor. SwiftAppleTarget now inherits from SwiftTarget, eliminating 9 duplicated methods.
  • New feature. publish() and build_assets() are now gated on target capabilities. Targets that don't declare the capability are skipped instead of calling no-op methods.
  • New feature. version_file() now accepts an optional dir_path parameter. DenoTarget uses it to resolve deno.json vs deno.jsonc dynamically.

#Fixes

  • Fix. Release confirmation prompt now shows the correct version filename for Deno projects using deno.jsonc.
  • Fix. PlainTarget no longer auto-detects alongside the docs target when both VERSION and selfdoc.json are present.
  • Fix. Flutter targets now show pubspec.yaml (flutter) in the target table instead of --- for detection files.

#0.61.1

Fix feature matrix column order and add directive tests.

#Fixes

  • Fix. Restored original display order for feature matrix columns (was inadvertently alphabetized).

#0.61.0

Target introspection: capabilities, ecosystem, and auto-generated target table.

Context

All 18 release targets now declare capabilities (publish, build_assets, read_name, read_metadata, ci_templates, dev_install), ecosystem labels, and auto-detectability. A new table-targets selfdoc directive auto-generates a comprehensive target details table, replacing the stale manual table. MATRIX_COLUMNS is now derived from TARGETS.keys() for DRY consistency.

#Features

  • Refactor. Feature matrix directive now uses selfdoc.tables.render_markdown_table and generate_feature_matrix_data() returns raw data instead of markdown.
  • New feature. All 18 release targets now declare capabilities, ecosystem, and auto_detectable attributes. Capabilities are a frozenset of strings (publish, build_assets, read_name, read_metadata, ci_templates, dev_install) describing what each target supports. Ecosystem is a human-readable label. Auto-detectable indicates whether the target can be auto-detected from project files.
  • New feature. Auto-generated target details table via :-: table-targets selfdoc directive, showing all 18 targets with ecosystem, detection files, version file, tag formats, capabilities, and dev install commands.
  • Refactor. MATRIX_COLUMNS in checks is now derived from TARGETS.keys() instead of a hardcoded tuple, ensuring the feature matrix stays in sync when targets are added.

#Fixes

  • Docs. Replaced stale manual target table in docs with auto-generated directive. Fixed all target count references across docs and CLI help strings (was 12/14/17, now 18).

#0.60.1

Feature matrix n/a support for toolchain-native checks

#Features

  • Feature matrix. Support "n/a" cells for checks where the toolchain already handles the concern natively (e.g., circular-deps for Go modules).

#0.60.0

Go workspace dependency validation, circular dependency detection, Dart dead-module detection, and feature matrix selfdoc directive.

#Features

  • Go workspace dependency validation. GoImportScanner enables deps-unused, deps-undeclared, deps-runtime-test-only, and deps-dev-in-lib checks for Go projects.
  • Circular dependency detection. New circular-deps quality check detects intra-package circular import chains using Tarjan's SCC algorithm. Per-language severity: Python=warn, npm=error. Go is skipped (compiler catches cycles).
  • Dart dead-module detection. The dead-modules check now supports Dart projects, finding unreachable files via entry-point reachability from pubspec.yaml barrel files and bin/ scripts.
  • Feature matrix directive. New table-feature-matrix selfdoc directive auto-generates a language support table in docs.

#0.59.1

Fix false-positive deps-undeclared findings in root-project dep scan when sibling project source files are present.

#Fixes

  • Fix. Root-project dep scan no longer produces false-positive deps-undeclared findings from sibling project source files.

#0.59.0

Unified manifest detection, PlainTarget auto-detection, monorepo sync template resolution, required template variables, and fixes for sub-directory scaffold operations and release-file commit exemption.

#Features

  • PlainTarget auto-detection. VERSION-only projects are now auto-detected without opt-in configuration.
  • Unified manifest detection. Target detection files are now derived from the target registry as a single source of truth, eliminating hardcoded manifest lists.
  • Required template variables. process_template now errors on missing critical variables at scaffold time instead of silently leaving placeholders.
  • Monorepo sync template resolution. monorepo sync now resolves template variables in per-project CI workflows instead of copying them verbatim.

#Fixes

  • Scaffold auto-commit and hook install from sub-directories. Scaffold auto-commit and pre-push hook installation now work correctly when run from monorepo sub-project directories.
  • Release file commits auto-exempted. Commits that only touch .rlsbl/releases/ files are now automatically exempted from changelog coverage checks.

#0.58.0

New dead-workspace-packages check for detecting unused library packages in monorepo workspaces

#Features

  • New check. dead-workspace-packages detects workspace library packages never imported by any sibling, with specific messaging for test-only imports.

#Fixes

  • Improved. Expanded monorepo release init command description for better selfdoc SEO.

#0.57.1

Fix Python 3.14 compatibility in monorepo release-init

#Fixes

  • Fix. monorepo release-init no longer crashes on Python 3.14 when rendering commented-out package sections. The tomlkit.dumps() call was replaced with tomlkit.item().as_string() to avoid a ValueError when serializing arrays.

#0.57.0

Batch release-init filtering, retry.toml cleanup, and feature support matrix

#Features

  • New. monorepo release-init now accepts a --packages flag to scaffold only specific packages. Packages with zero unreleased commits are automatically commented out with an explanation.
  • New. Feature support matrix: get_feature_matrix() and generate_feature_matrix_markdown() functions showing which checks support which targets.

#Fixes

  • Fix. retry.toml is now cleaned up when validation fails during release retry, in both the init and retry handlers. Previously, an invalid retry.toml could be left behind, blocking subsequent retries.

#0.56.0

New checks (license-file, scaffold-unreplaced-vars, dead-modules-npm), batch release-init improvements, and scaffold/release fixes

Context

LICENSE is no longer scaffold-managed -- projects own their LICENSE file, enforced by the new license-file check. Batch release-init now supports Flutter targets and includes TOML comments. Several fixes for retry.toml cleanup, bare scaffold on plain targets, workspace-unregistered false positives, and shared release config validation.

#Breaking

  • LICENSE removed from scaffold. Projects must now manage their own LICENSE file. The license-file check enforces its presence.

#Features

  • npm dead module detection. New dead-modules-npm check detects unreachable modules in npm packages by tracing entry-point reachability through the dependency graph.
  • New checks. license-file errors if LICENSE is missing, empty, or contains template variables. scaffold-unreplaced-vars detects leftover template variables in scaffold-generated files.
  • Batch release-init improvements. Flutter targets now get per-target config sections. Release files include TOML comments and the context field.

#Fixes

  • Fix retry.toml blocking release. release retry now cleans up the scaffolded retry.toml when validation fails, preventing it from blocking subsequent release run attempts.
  • Fix bare scaffold for plain targets. rlsbl scaffold now reads targets from config.json for already-scaffolded projects that use plain targets, instead of erroring.
  • Fix workspace-unregistered false positives. The check now skips private package.json files and parent directories of registered projects.
  • Shared release config validation. Single and batch release paths now use a shared validator, fixing missing Flutter validation in the batch path.

#0.55.0

Monorepo release-init command, Go dead-modules detection, scaffold and workspace check fixes

#Features

  • New command. monorepo release-init scaffolds a batch release file with per-package sections for all workspace projects.
  • New feature. dead-modules check now supports Go projects. Detects unreferenced internal/ packages via tree-sitter import scanning.

#Fixes

  • Fix. Template sheltering now handles dotted placeholders like {{zig.projectName}}, preventing YAML corruption in multi-target scaffold.
  • Fix. Scaffold with explicit --target now uses the current directory as project root, fixing dev_node detection for plain-target projects in monorepos.
  • Fix. Workspace stale-entries and unregistered checks now recognize all 16 target manifest types plus .rlsbl/config.json as a universal project indicator.

#0.54.2

Batch release description enforcement, scan cache optimization, lint exclusion todo cleanup

#Fixes

  • Fix. Batch release files now enforce mandatory description per package, matching single-release behavior.
  • Fix. Dep quality checks now share a cached import scan instead of scanning 4x per workspace project.

#0.54.1

Make release description mandatory

#Breaking

  • Breaking. Release description is now mandatory in unreleased.toml. Every release must have a short summary.

#0.54.0

Dev node architecture, release descriptions, quality checks, and graph enhancements

Context

The changelog_exempt flag (v0.53) was renamed to dev_node because agents misinterpreted exempt as a desired behavior rather than a graph position. Dev nodes now fully opt out of the changelog system instead of being exempted from enforcement.

#Breaking

  • Breaking. Renamed changelog_exempt to dev_node. Dev node projects no longer participate in the changelog system — no JSONL entries, no CHANGELOG.md, no pre-push enforcement. Release does version bump + tag + GitHub Release (body from release description). Boundary guardrail prevents non-dev-nodes from depending on dev_nodes at runtime.

#Features

  • Internal. Added WorkspaceProject typed wrapper and project field on ProjectContext for structured workspace project access.
  • New feature. Release description and context fields in unreleased.toml. Description appears in CHANGELOG.md under version heading. Context appears as collapsible details block. Description mandatory for dev_node releases.
  • New feature. Three quality checks: deps-runtime-test-only (warning: runtime dep only used in tests), deps-dev-in-lib (error: dev dep imported in lib code), dead-modules (warning: Python modules with zero intra-project references).

#Fixes

  • Fix. Library lint now excludes test and example files by default. Go *_test.go, Python test_*.py/tests/, npm *.test.ts/__tests__/, and examples/ dirs are no longer flagged for stdout usage.

#0.53.0

#Breaking

  • Breaking. Renamed internal workspace flag to changelog_exempt. The new name describes the behavior (changelog enforcement exemption), preventing misuse.

#Features

  • Internal. Added scope field to Dependency namedtuple (runtime/dev/peer/explicit). Reverse dependency graph now supports scope-filtered traversal.

#0.52.0

#Breaking

  • Breaking. All target methods (template_mappings, read_name, write_version) now require ctx parameter (no default). Fixed _is_library CWD bug in template_mappings.

#Features

  • New feature. internal = true workspace flag. Internal projects are fully exempt from changelog enforcement: no JSONL entries needed, pre-push check skips them, no user-facing requirement. Version bumps and GitHub Releases still work.
  • New feature. deps-unused check now scans JS/TS imports via tree-sitter. npm workspace dependencies (workspace:*) are no longer false-positived as unused.

#Fixes

  • Fix. Go target no longer misdetects cmd-layout projects (cmd/*/main.go) as libraries. Scaffold now correctly includes publish.yml and .goreleaser.yml for these projects.
  • Fix. Standalone multi-target publish workflows now inject working-directory, packages-dir, and version-file paths for targets in subdirectories. Refactored to structured YAML.

#0.51.0

#Breaking

  • Breaking. Renamed monorepo_root to workspace_root on ProjectContext. Deleted ProjectCheckContext — all check functions now receive ProjectContext with pre-loaded config.
  • Breaking. All target methods (template_vars, shared_template_mappings, read_name, write_version, publish) now accept ctx: ProjectContext instead of project_root. Fixed latent bugs where dart write_version and docker read_name didn't receive config.

#Features

  • Internal. Added [tool.uv.sources] for editable strictcli install.

#0.50.0

#Breaking

  • Breaking. Config utility functions (should_tag, get_push_timeout, push_if_needed, read_deploy_config, get_publish_config) now accept a config dict instead of project_root. write_project_config returns the updated dict.
  • Breaking. All target publish() methods now accept ctx: ProjectContext instead of project_root. Config is read from ctx.config — no redundant disk reads during publish.

#Features

  • Internal. Extracted shared _rel_to_git_root utility, eliminating duplicate path normalization in release flow.
  • Internal. Added regression test for release abort cleanup (unexpected-files scenario).

#0.49.2

#Features

  • Internal. Commands that don't read config no longer load it at startup. Scaffold commands use ProjectContext for direct config access.
  • Internal. Added release integration tests exercising the full release flow against real git repos (no mocked subprocess calls).

#Fixes

  • Fix. Increased npm check-name timeout from 10s to 30s to reduce CI flakiness on cold-cache runners.
  • Fix. Changelog finalization now uses git-relative paths consistently, matching the version-bump commit's path format.
  • Fix. Monorepo release lock file now uses the correct root path.

#0.49.1

#Fixes

  • Fix. Monorepo release commits now use correct relative paths for version-bumped files.

#0.49.0

#Breaking

  • Breaking. Release, pre-push check, deploy, and undo commands now receive ProjectContext instead of bare project_root. Config is read once at startup via ctx.config instead of re-reading from disk at each call site.

#Fixes

  • Fix. Configuration docs no longer trigger stale-description warnings on every release. The version field is excluded from the selfdoc.json schema table.
  • Fix. Adapted check system bootstrap for strictcli v0.11 API (required app field in checks.toml).

#0.48.2

#Fixes

  • Fix. Lockfile modifications from version bump no longer falsely flagged as concurrent changes during release.

#0.48.1

#Fixes

  • Fix. rlsbl scaffold no longer crashes for Go, Zig, and Docker projects (missing project_root argument in template_vars/shared_template_mappings).

#0.48.0

#Breaking

  • Breaking. All internal APIs now require explicit project_root parameter (no silent CWD fallback). Eliminates the last footgun from the os.chdir removal.

#Fixes

  • Fix. Release aborts (e.g., unexpected dirty files) now revert version-bumped files instead of leaving the working tree dirty. Prevents selfdoc hash oscillation on subsequent releases.
  • Fix. Corrupt .rlsbl/config.json now raises a clear error with the file path instead of silently returning empty config.
  • Fix. Release lock file is now created relative to the project root, not CWD.

#0.47.0

#Breaking

  • Breaking. release init scaffolds bump = "" (was "patch") and release retry scaffolds ref = "" (was the tag). Both fields must now be set explicitly. Scaffolded files include explanatory TOML comments.

#Features

  • New flag. watch --run-id monitors CI runs by ID instead of commit SHA. Accepts multiple values (--run-id 123 --run-id 456). Mutually exclusive with the SHA positional arg.
  • Retry + watch integration. release retry now captures dispatched workflow run IDs and passes them to watch --run-id, so monitoring works correctly even when the dispatch ref differs from the release tag.
  • CI sync rewrite. Monorepo CI sync transforms rewritten from text-based to structured YAML (ruamel.yaml round-trip mode). working-directory is now injected per-job (not workflow-level), correctly handling cross-project CI workflows.
  • Monorepo scoping. status and unreleased now filter commits by project directory in monorepo mode, showing only commits that touch the current project's files.

#Fixes

  • Fix. changelog add in monorepo sub-projects no longer writes to the root JSONL file. Path resolution uses explicit project root instead of CWD.
  • Fix. Config reads (push_timeout, publish config, deploy config, etc.) no longer fail silently after CWD shifts during monorepo releases. All config functions accept explicit project_root.
  • Fix. Release no longer falsely aborts with 'unexpected modified files' when project_root is an absolute path.

#0.46.0

#Breaking

  • Breaking. --update flag removed from scaffold. Bare rlsbl scaffold is now idempotent — creates what's missing, three-way merges what exists. Run it anytime.

#0.45.1

#Fixes

  • Bug fix. Scaffold now creates non-workflow files (like .npmignore) from all targets, not just the primary.
  • Bug fix. Docker publish template no longer has {{version}} replaced by the literal version. Added escape syntax (\{{...}}) to the template engine.
  • Bug fix. Scaffold now uses the correct subdirectory path for npm targets instead of always looking at the repo root.
  • Docs. release retry help text updated to describe dispatch-only behavior.

#0.45.0

#Breaking

  • Breaking. push_timeout must now be explicitly set in .rlsbl/config.json or via RLSBL_PUSH_TIMEOUT env var. The implicit 120-second default is removed.

#Features

  • Improvement. The plain release target now bumps pyproject.toml version when present, keeping it in sync with VERSION.

#Fixes

  • Bug fix. release run now correctly applies directory scoping for monorepo changelog validation, matching rlsbl check --tag changelog behavior.
  • Bug fix. Changelog checks now use the target-specific tag pattern in monorepos (e.g., go/v* for Go targets instead of go@v*).

#0.44.0

#Breaking

  • Breaking. release retry is now dispatch-only. It no longer deletes/re-creates the GitHub Release or re-uploads assets. It dispatches workflows from retry.toml via gh workflow run. Schema simplified to 3 fields: version, dispatch, ref.

#0.43.1

#Features

  • Scaffold. npm targets now get a .npmignore file with sensible defaults, preventing non-npm content from being published.

#Fixes

  • Bug fix. release retry now always dispatches all workflows listed in retry.toml, not just as a fallback when no runs are found. Fixes CI never being re-triggered when Publish triggers naturally.

#0.43.0

#Breaking

  • Breaking. edit-release, undo, and yank are now subcommands of the release group: release edit, release undo, release yank.
  • Breaking. release retry is now file-driven via retry.toml. Auto-scaffolds the file with defaults when not present. The version positional argument is removed.

#Features

  • Improvement. release yank now shows a confirmation prompt before destructive operations, with --yes to bypass.
  • Improvement. release run now detects monorepo root and errors with guidance to use monorepo release.

#Fixes

  • Bug fix. Multi-target scaffold now correctly includes workflow_dispatch in merged publish workflows.
  • Bug fix. selfdoc.json version is now auto-bumped during release even when docs is not in the configured targets. The version-consistency check also detects drift independently of target config.
  • Bug fix. Monorepo changelog coverage now only requires entries for commits touching the package's own files, not all commits in the range.
  • Bug fix. release yank now uses correct monorepo tag format instead of hardcoding v{version}.

#0.42.0

#Breaking

  • Breaking. rlsbl release is now a command group. Use rlsbl release run (was rlsbl release), rlsbl release init (was rlsbl release-init), and the new rlsbl release retry.
  • Breaking. rlsbl release run requires --watch or --no-watch. --watch auto-monitors CI to completion; --no-watch prints the watch hint.

#Features

  • New command. rlsbl release retry re-creates a GitHub Release to re-trigger CI/CD workflows, with asset re-upload and automatic gh workflow run fallback.
  • Scaffold. All generated CI and Publish workflow templates now include workflow_dispatch trigger for manual re-triggering after GitHub Actions outages.
  • Watch. rlsbl watch now suggests rlsbl release retry when no CI runs are found but a GitHub Release exists for the commit.
  • New target. pgdesign release target for database schema projects.

#Fixes

  • Bug fix. rlsbl check commands no longer crash in monorepo context with WorkspaceGraph.__init__() missing required argument.

#0.41.7

#Features

  • New feature. Releases are now blocked when there are no user-facing changelog entries. Shown as a warning during rlsbl check, hard error during rlsbl release.
  • New feature. changelog add and changelog amend now detect duplicate commits -- hard error when the same commit appears in an entry with matching type, warning when types differ.

#Fixes

  • Fix. DocsTarget version sync now also updates the last entry in selfdoc.json versions array, preventing VER003 lint failures after release.

#0.41.6

#Features

  • New feature. Run selfdoc gen --no-commit before selfdoc check during release, ensuring docs are regenerated from source before validation.

#Fixes

  • Fix. selfdoc check failures now print a clean error message instead of a raw Python traceback.

#0.41.5

#Fixes

  • Fix. Detect npm moniker collisions for separator-free names. Previously, check-name pgspec --target npm reported "available" even though pg-spec exists and npm considers them identical. Now generates insertion variants (inserting -, ., _ at every position) and checks each. Also fixed dot separator handling -- dots are now treated identically to dashes and underscores, matching npm's actual normalization.

#0.41.4

#Fixes

  • Fix: selfdoc hashes no longer left dirty after release. Content hashes are refreshed after the version bump so the working tree stays clean post-release.

#0.41.3

#Features

  • DocsTarget is now a versioned target. Reads and writes version from selfdoc.json. The version-consistency check now includes docs targets instead of skipping them.

#0.41.2

#Features

  • Go assets use goreleaser for cross-compilation. When goreleaser is installed, build_assets() produces binaries for linux/darwin/windows x amd64/arm64. Falls back to host-only go build when goreleaser is unavailable.

#0.41.1

#Breaking

  • **Breaking: .claude/settings.json removed from scaffold templates.** Claude Code does not require this file. Projects with customized hooks keep their existing file.

#Features

  • Config validation and migration. Release flow now validates publish.<target>.assets config. scaffold --update auto-detects missing private key. New config-schema check (29 checks total). Removed get_max_asset_size_mb() implicit default.

#Fixes

  • **Fix: library-lint check skips non-library projects.** Standalone projects no longer produce 523 spurious lint errors in rlsbl check --all.

#0.41.0

#Breaking

  • **Breaking: private config key is now required.** No implicit default. Set "private": true for private repos or "private": false for public repos. Private repos are blocked from publishing to public registries.
  • Breaking: private hook template removed. The post-release-private.sh.tpl scaffold template is deleted. Asset upload is now a built-in release step configured via publish.<target>.assets. A new private-hook-stale check detects legacy private hooks.
  • Breaking: CLAUDE.md removed from scaffold templates. Projects using selfdoc root file templates should manage CLAUDE.md via docs/_CLAUDE.md. Scaffold no longer creates or updates CLAUDE.md.
  • **Breaking: run_cmd legacy signature removed.** The release command no longer accepts run_cmd(registry, args, flags). Use ReleaseConfig from rlsbl.release_file instead.

#Features

  • **New command: changelog amend.** Amend historical changelog entries in released JSONL files. Unlocks the file, appends the entry, re-locks, regenerates CHANGELOG.md, and syncs GitHub Release notes via edit-release.
  • **Per-target build_assets().** New target method for building distributable artifacts. Implemented for PyPI (uv build), npm (npm pack), Go (go build), and Cargo (cargo build --release).
  • Release asset upload. Configure publish.<target>.assets: true and max_asset_size_mb to build and upload artifacts to GitHub Releases during rlsbl release. Size guard aborts if artifacts exceed the limit.
  • Auto-dump strictcli schema during release. Projects with strictcli in their dependencies automatically run --dump-schema during release. Changed .strictcli/schema.json is included in the release commit.
  • Selfdoc check runs earlier in release pipeline. Moved from after lint to after pre-checks hook, catching staleness errors before tests run.

#Fixes

  • Fix: noop commit warnings eliminated. Monorepo sync, monorepo snapshot, and validation cache no longer warn when nothing changed. Prints a clear skip message instead.
  • **Fix: release-init no longer refuses empty files.** An empty or whitespace-only unreleased.toml left after finalization no longer blocks release-init.
  • Fix: version-consistency check no longer fails on DocsTarget. Targets with no version file (like docs) are skipped in the version comparison.

#0.40.1

#Fixes

  • Fix. CI workflow updated for the check to check-name rename.

#0.40.0

#Breaking

  • **Breaking: removed --skip-tests, --skip-lint, --skip-docs, --skip-remote-check, and --no-tag flags from the release command.** Tests, lint, and remote checks now always run. Selfdoc check is automatically skipped when docs target is excluded in the release file. Only --allow-dirty remains as a release-specific flag.

#Features

  • selfdoc root file templates. README.md and CLAUDE.md are now auto-generated by selfdoc from docs/_README.md and docs/_CLAUDE.md templates. Edit the templates, not the generated files.

#0.39.0

#Breaking

  • Breaking: file-based releases. rlsbl release now reads from .rlsbl/releases/unreleased.toml instead of CLI args. Run rlsbl release-init to scaffold the file. The file declares bump type, included/excluded targets, and per-target config.
  • **Breaking: rlsbl doctor, monorepo lint, and changelog validate removed.** Replaced by the unified rlsbl check command. Use rlsbl check --all, rlsbl check --tag workspace, or rlsbl check --tag changelog.
  • **Breaking: --dry-run, --yes, --quiet are now global flags.** They apply to all commands. Both rlsbl --dry-run release and rlsbl release --dry-run work.
  • Breaking: PyYAML replaced with ruamel.yaml. Projects extending rlsbl's YAML handling must use the ruamel.yaml API.
  • Breaking: rlsbl check (name availability) renamed to rlsbl check-name to make room for the unified check system.

#Features

  • Unified check system. 27 checks migrated to strictcli's @app.check() framework. Run rlsbl check --all, filter by tag (--tag project, --tag changelog, --tag workspace, --tag release), or by name (--name lock). Supports dependency ordering, JSON output, dry-run, and verbose modes.
  • Dart target and workspace scanner. New dart target type: reads/writes pubspec.yaml version field with round-trip formatting preservation. DartScanner detects intra-workspace dependencies in Dart monorepos.
  • Flutter iOS/Android targets with Shorebird OTA. Separate flutter-ios and flutter-android targets with platform-specific tags. Release file mode field (ota/build) controls release type. Native file detection blocks OTA when platform code changes. Build number (+N) management opt-in via config.
  • **monorepo graph command.** Export the workspace dependency graph as JSON, DOT (Graphviz), or indented text. Filter with --root (transitive deps), --reverse (transitive rdeps), and --depth.
  • **monorepo snapshot command.** Generates .rlsbl-monorepo/snapshot.json summarizing all packages, versions, deps, and graph structure. --check mode for CI staleness detection. Auto-regenerates during monorepo releases.
  • Architectural layer rules. Define [layers] in workspace.toml with ordered layers and glob-based package assignments. The layers-violations check enforces dependency direction. Supports unrestricted packages, forbidden targets, and explicit cross-layer allowances.
  • Dependency-import validation. New deps-unused and deps-undeclared checks scan source files (Python via tree-sitter, Dart via regex) to verify declared dependencies match actual imports. Whitelist via .rlsbl-monorepo/dep-overrides.toml.
  • **monorepo impact command.** Analyze blast radius of changes: input a package name, file paths, or git range (--since). Outputs direct/transitive dependents, test scope, and release candidates in JSON or text.
  • Coordinated multi-package releases. monorepo release reads a batch release file (.rlsbl-monorepo/releases/unreleased.toml) and releases packages in topological order. New deps-stale check detects outdated intra-workspace constraints. Advisory constraint propagation after each release.

#0.38.2

#Fixes

  • Fix. Publish router no longer fails for plain-target releases. Added a no-op job so GitHub Actions workflows succeed even when all conditional publish jobs are skipped.

#0.38.1

#Features

  • Hook-generated files included in release commit. Files modified or created by pre-checks and pre-release hooks are now automatically detected and included in the release commit, instead of being left dirty.

#Fixes

  • Fix PyPI build for subdirectory targets. uv build --out-dir no longer produces a doubled path (e.g. pypi/pypi/dist) when the pypi target lives in a subdirectory.

#0.38.0

#Breaking

  • Monorepo publish router inlines jobs. monorepo sync now inlines each sub-project's publish steps directly into the root publish.yml instead of calling per-project reusable workflows via workflow_call. This fixes PyPI Trusted Publishing (OIDC), which rejects tokens from reusable workflows. Per-project source workflows stay on: release (standalone-ready). Old {name}-publish.yml wrappers are auto-deleted on sync.

#Features

  • Publish router hash cache. monorepo sync now caches SHA256 hashes of per-project publish workflows in .rlsbl-monorepo/publish-cache.json and skips router regeneration when nothing changed.

#Fixes

  • **Fix Zig npm-wrapper needs: dependency.** build_npm_publish_jobs() no longer hardcodes needs: [goreleaser] -- Zig projects now correctly use needs: [build-and-upload].
  • **Fix monorepo sync self-reference with path=".".** Projects with path="." no longer wrap the generated router as their own publish workflow.

#0.37.0

#Features

  • New feature. Auto-sync lockfiles during release. After version bump, rlsbl detects uv.lock, package-lock.json, and go.sum, runs the appropriate sync command, and includes modified lockfiles in the release commit.

#Fixes

  • Fix. Restore path-based changelog-only commit exemption alongside the Autogenerated trailer check. Manual commits touching only .rlsbl/changes/ or CHANGELOG.md are now correctly skipped during coverage validation.
  • Fix. Skip gitignored lockfiles during release lockfile sync. Previously, syncing a lockfile that was in .gitignore caused git add to fail and aborted the release.

#0.36.1

#Fixes

  • Fix. Monorepo target detection now resolves project paths relative to the monorepo root, not the current directory. Fixes changelog validation and status reporting when running from inside a sub-project.
  • Fix. uv build and uv publish now run from the sub-project directory in monorepo mode, fixing build failures for PyPI targets.

#0.36.0

#Features

  • New feature. Asset size guard in private post-release hook -- checks files in dist/ against max_asset_size_mb (default 2MB) before uploading to GitHub Releases.

#0.35.1

#Features

  • Cleanup. Changelog commit exemption now uses only the Autogenerated: true trailer; old path-pattern fallback removed.

#Fixes

  • Bug fix. Release finalization now generates the per-version .md file alongside the JSONL.
  • Bug fix. Release flow no longer false-positives on files written by hooks, lint, or changelog generation.

#0.35.0

#Features

  • **rlsbl release warns about stale changelog entries in monorepo mode.** During finalization, entries referencing commits outside the unreleased range are flagged to stderr (warn-only; no entries stripped) so out-of-range entries don't silently carry into the next release cycle.
  • **Template action versions now use {{action "name"}} placeholders.** GitHub Action versions in scaffold templates are resolved at scaffold time from rlsbl/data/action_versions.toml, eliminating duplication between the table and 60+ template references. Updates to action versions now require editing only the table.

#Fixes

  • Release flow no longer crashes when extracting the changelog entry. Fixed a regression introduced in v0.34.0 where the in-memory preview of generate_changelog used ## Unreleased as the heading but entry extraction looked for ## X.Y.Z, returning None and crashing later in GitHub Release notes generation. The preview call now passes version_override=new_version so the heading matches.
  • **max_entries_per_commit default raised from 2 to 5.** The previous default 2 was too strict and contradicted the documented practice that one commit can appear in multiple JSONL entries (e.g., fix + feature). Default now matches the existing max_commits_per_entry default of 5.

#0.34.0

#Features

  • Configurable changelog batch-limits validation. rlsbl changelog validate now checks that no entry has more than max_commits_per_entry (default 5) commits and that no commit appears in more than max_entries_per_commit (default 2) entries. Both limits configurable per project via the batch_limits section in .rlsbl/config.json. Known violations can be silenced via an exclusions list with a required reason field for audit purposes.

#0.33.0

#Features

  • **rlsbl dev install expanded.** New --global (default) and --venv flags. Added support for hex, deno, zig, and swift targets in addition to pypi/npm/go/cargo. For pypi/npm, --venv installs into the project's local environment (uv sync / npm install).

#Fixes

  • PyPI publish error names both env vars. When the PyPI publish credential is missing and no token_var override is configured, the error message now reads 'no PYPI_TOKEN or TWINE_PASSWORD' instead of hardcoding only PYPI_TOKEN.
  • Em-dash in status warning. rlsbl status's 'commits ahead' warning now uses an em-dash separator (— run) instead of two hyphens (-- run).
  • **Empty release_branches config is now an error.** Previously an explicit empty list silently fell back to ['main','master'] and disabled the manual-push warning. To opt out of the warning, remove the release_branches key entirely; to limit to specific branches, list them.
  • **rlsbl release no longer pollutes the working tree on abort.** Previously, when a pre-mutation check (selfdoc, tests, lint, hooks) failed, the regenerated CHANGELOG.md was left in the working tree and had to be manually reverted. The write is now deferred until after all pre-checks pass.

#0.32.0

#Features

  • Status warning for unreleased commits. rlsbl status now prints a prominent ! N commits ahead of <tag> warning when the current project has unreleased commits since its last tag.
  • Centralized GitHub Actions versions. All scaffolded workflows now read action versions from a single table (rlsbl/data/action_versions.toml), and actions/checkout has been bumped to v6 across every template ahead of the June 2026 Node 20 deprecation.
  • **scaffold --dry-run.** Preview which files would be created, updated, conflicted, or unchanged without writing anything.
  • **scaffold --update regenerates stale pre-push hooks.** Known-old hook contents are recognized by content hash and overwritten with the current template; user-customized hooks are preserved and a unified diff is printed for manual review.
  • Pre-push hook warns on manual release-branch pushes. Pushing to main/master outside rlsbl release now prints a prominent warning (configurable via release_branches in .rlsbl/config.json). The push is not blocked.
  • Config-driven per-target publish gating. A new publish section in .rlsbl/config.json declares local: true|false and token_var overrides per target, replacing ad-hoc env-var-presence checks across all 7 publishable targets.
  • **New rlsbl dev install command.** Locally installs the current project in editable mode based on its target (pypi → uv tool install -e ., npm → npm link, go → go install ./..., cargo → cargo install --path .). Supports --uninstall, and in monorepos: --all, --include, --exclude.
  • **User-owned ci-custom.yml and publish-custom.yml.** Customize CI without three-way merge conflicts by adding your own jobs in a separate workflow file that rlsbl scaffold never touches.
  • **--no-commit flag on rlsbl monorepo init/add/sync.** Consistent with scaffold and changelog; enables batched migrations into a single commit.

#Fixes

  • Go monorepo tag bug fix. Release in a Go monorepo no longer produces malformed tags like auth-gatewayv0.1.0 when the workspace.toml path lacks a trailing slash — the separator is now inserted defensively, and workspace paths are normalized at load time.
  • Monorepo publish workflows now run on release. The generated publish router declares per-target permissions: and secrets: inherit, fixing the startup_failure that affected every monorepo publish run on GitHub Actions.
  • **scaffold --update no longer commits files with merge conflict markers.** Conflicted files are excluded from the auto-commit and listed so they can be resolved manually.
  • Docs target no longer fails when Cloudflare credentials are missing. DocsTarget.publish() gracefully skips selfdoc deploy when CF_ACCOUNT_ID or CF_PAGES_API_TOKEN is absent, instead of producing a hard subprocess error on every release.
  • **Autogenerated: trailer uses git's --trailer flag.** rlsbl-created commits now record the trailer via git commit --trailer instead of embedding it in the commit message body. This makes the trailer correctly parseable by git interpret-trailers and other git tooling, which previously couldn't read the embedded form.

#0.31.0

#Breaking

  • Breaking. Go targets in monorepos now use path-based tags (go/v0.1.1) instead of name-based ([email protected]), matching Go module proxy requirements. All tag discovery and matching updated.

#Features

  • Feature. Go CLI projects automatically run go install after release to update the local binary.
  • Feature. selfdoc check runs automatically during release when selfdoc.json exists. Skip with --skip-docs.

#Fixes

  • Fix. Commits touching only changelog infrastructure files (.rlsbl/changes/, CHANGELOG.md) are again exempt from coverage, even without the Autogenerated trailer.
  • Fix. Release flow now rolls back locally on push failure: deletes the tag, resets commits, and prints recovery instructions. Branch and tag are pushed in a single git push command.
  • Fix. rlsbl undo now handles the two-commit release pattern (version bump + changelog finalize), reverting both and restoring JSONL state.

#0.30.1

#Features

  • Feature. All commit_files() calls now default to autogenerated=True, ensuring every rlsbl-generated commit carries the Autogenerated: true trailer.
  • Feature. Pre-push hook now blocks pushes when unreleased.jsonl, .validated, or CHANGELOG.md are gitignored.

#Fixes

  • Fix. .validated cache is no longer gitignored; tracked per project rules.
  • Fix. Pre-push hook now reads all JSONL files (unreleased + versioned) for coverage, fixing release pushes being blocked after changelog finalization.

#0.30.0

#Breaking

  • Breaking. Changelog coverage exemption now uses the Autogenerated: true git trailer instead of file-path pattern matching and commit-message regexes. Auto-generated commits must carry this trailer to be exempt.

#Features

  • New command. rlsbl commit commits files with an Autogenerated: true git trailer, marking them as auto-generated for changelog coverage exemption.
  • Feature. Changelog finalization, rlsbl changelog add, and rlsbl changelog generate auto-commits now carry the Autogenerated: true trailer.
  • Feature. Pre-push hook skips JSONL coverage check when pushing a version tag (standalone v* or monorepo name@v*).

#0.29.1

#Fixes

  • Fix. Release no longer aborts when the .validated changelog cache is updated during validation.

#0.29.0

#Features

  • New command. rlsbl monorepo lint detects unregistered projects and stale workspace entries.

#Fixes

  • Fix. Pre-push hook now recognizes monorepo release commit messages and filters coverage checks to only commits affecting each sub-project.
  • Fix. Release commit now includes all version files modified by targets (__init__.py for PyPI, build.zig.zon for Zig, dynamically-chosen file for Maven).
  • Fix. Built-in tests, lint, and hook scripts now run from the correct sub-project directory in monorepo mode.
  • Fix. Changelog validation, rlsbl status, and rlsbl changelog validate now use project-scoped tags (<name>@v*) in monorepo mode.
  • Fix. rlsbl undo now correctly finds project-scoped tags and matches monorepo release commit messages.

#0.28.1

#Fixes

  • Fix: status applies changelog-only exemptions. rlsbl status now excludes changelog-only commits from the JSONL coverage count, consistent with changelog validate. Shows exemption count when applicable.
  • Fix: gitignore uses set-union merge on scaffold update. scaffold --update now appends new entries to .gitignore without three-way merge, eliminating predictable conflicts. No lines are removed or reordered.
  • Fix: backfill script uses CWD as default project root. scripts/backfill_changelog.py now operates on the current directory instead of hardcoding rlsbl's own root. Accepts --project-root for explicit override.

#0.28.0

#Breaking

  • Revert: strict type validation removed. Changelog entry types are freeform strings again. Non-standard types render under "Other" in generated CHANGELOG.md. Formalization deferred until real-world usage patterns emerge.

#Features

  • **changelog generate auto-commits.** Generated CHANGELOG.md and per-version .md files are now auto-committed after generation. Use --no-commit to skip.

#Fixes

  • **Fix: monorepo publish workflow renamed to publish.yml.** The monorepo publish router was named publish-router.yml, which broke PyPI Trusted Publishing OIDC claims when projects moved between standalone and monorepo layouts. Now always publish.yml in both contexts.
  • Fix: monorepo sync handles trailing slashes, version-file paths, and packages-dir. Sync no longer produces double-slash globs from workspace.toml paths with trailing slashes. Action inputs like go-version-file are rewritten to include the sub-project path. pypa/gh-action-pypi-publish gets packages-dir injected when working-directory is set.
  • **Fix: monorepo publish workflow renamed to publish.yml.** The monorepo publish router was named publish-router.yml, which broke PyPI Trusted Publishing OIDC claims. Now always publish.yml in both standalone and monorepo contexts.
  • Fix: monorepo sync handles trailing slashes, version-file paths, and packages-dir. Sync no longer produces double-slash globs. Action inputs like go-version-file are rewritten for sub-project paths. pypa/gh-action-pypi-publish gets packages-dir injected.

#0.27.0

#Breaking

  • Breaking: JSONL changelog required. rlsbl release now requires .rlsbl/changes/ to exist. The manual CHANGELOG.md heading check fallback has been removed. Run rlsbl scaffold --update to set up JSONL changelogs.
  • Breaking: old lint.toml ignore format removed. The deprecated flat ignore key in .rlsbl/lint.toml is no longer supported. Use per-language config in .rlsbl/lint/python.toml etc.
  • **Breaking: get_* method aliases removed from BaseTarget.** Target implementations now use bare method names (version_file, template_dir, etc.) matching the ReleaseTarget protocol.
  • Breaking: lint returns empty results when no language detected. Previously defaulted to Python scanning; now requires a language marker file (pyproject.toml, go.mod, package.json).

#0.26.1

#Fixes

  • Fix: Watch CI hint points to the correct commit. The release command now captures the pushed SHA before running post-release hooks, so rlsbl watch targets the release commit instead of a post-hook auto-commit.

#0.26.0

#Features

  • **rlsbl yank command.** Deprecate or delete past releases. Soft yank (rlsbl yank v1.2.3) marks the GitHub Release as a pre-release with a deprecation notice. Hard yank (rlsbl yank v1.2.3 --hard) deletes the GitHub Release and its git tag entirely.
  • **PyPI release bumps __version__.** Python source files containing __version__ are now updated alongside pyproject.toml during release, keeping runtime version introspection in sync.
  • Strict type validation for JSONL entries. Changelog entries with user_facing: true now require type to be one of feature, fix, or breaking. Unrecognized types are rejected during validation and changelog add.

#Fixes

  • Fix: scaffold stays in sub-project directory. In monorepos, rlsbl scaffold no longer walks up to the repo root when project files already exist in the current directory. Previously this caused scaffold to operate on the wrong project.

#0.25.4

  • No user-facing changes.

#0.25.3

#Fixes

  • Fix: tag-based range for changelog validation. Unreleased commit detection now uses <last_tag>..HEAD instead of origin/main..HEAD. This correctly answers "what hasn't been released" rather than "what hasn't been pushed," and works regardless of branch naming convention or remote configuration.

#0.25.2

  • No user-facing changes.

#0.25.1

#Fixes

  • Fix: built-in lint only runs on library projects. The pre-release lint check no longer runs on CLI applications, avoiding false positives for print() calls and entry points. Lint runs only for monorepo projects with library = true.
  • Fix: CHANGELOG.md regenerated after JSONL finalization. The release command now regenerates CHANGELOG.md after renaming unreleased.jsonl to the versioned file, so the changelog heading shows the version number instead of "Unreleased".

#0.25.0

#Features

  • Structured JSONL changelog. Changelog entries are now backed by structured JSONL files in .rlsbl/changes/. Each entry maps a description to commit hashes with user_facing and type fields. rlsbl changelog add/validate/generate commands manage entries. rlsbl release auto-validates coverage and generates CHANGELOG.md. Pre-push blocks on missing coverage. rlsbl unreleased uses exact hash matching. rlsbl status shows coverage info. Scaffold creates the directory for new projects. changelog add auto-commits entries (with --no-commit opt-out). Coverage validation skips changelog-only commits. Internal commit logic centralized via commit_files helper. Pre-push hook compatible with strictcli argument handling.
  • Changelog backfill script. scripts/backfill_changelog.py migrates an existing CHANGELOG.md into JSONL files by parsing entries, mapping them to commits via keyword matching, and writing per-version JSONL files.

#Fixes

  • Fix: selfdoc CLI documentation. Replaced incompatible code-help directives with auto-generated CLI docs via selfdoc gen, fixing the build warning after the strictcli migration.
  • Fix: monorepo commands commit without safegit. monorepo init, add, and sync now properly fall back to plain git when safegit is not installed, instead of silently skipping the commit.
  • Fix: pre-push hook compatibility with strictcli. The pre-push hook no longer passes extra arguments that strictcli rejects. Release pushes (containing a version bump commit) skip the JSONL coverage check entirely since validation already ran during rlsbl release.

#0.24.0

#Features

  • **rlsbl edit-release [version].** New command that updates GitHub Release notes from CHANGELOG.md. Auto-detects the current version if none is given. Supports --dry-run to preview without changes.

#0.23.1

  • No user-facing changes.

#0.23.0

#Breaking

  • Breaking: hooks are now scaffold-managed. pre-release.sh and post-release.sh are no longer user-owned. scaffold --update merges template improvements into existing hooks via three-way merge.
  • **Breaking: rlsbl init removed.** The init alias for scaffold has been dropped. Use rlsbl scaffold directly.
  • **Breaking: --registry flag removed.** Use --target instead. The --registry flag was deprecated since 0.20.0.

#Features

  • Per-command help. CLI dispatch migrated to strictcli. Every command and monorepo subcommand now has its own --help with typed flags, arguments, and descriptions.
  • Multi-ecosystem library lint. Library boundary lint now supports Go and npm in addition to Python. Go lint detects forbidden imports (net/http, cobra, urfave/cli), fmt.Println, and func main(). npm lint detects forbidden imports (express, koa, commander, etc.), console.log, and bin entry points.
  • AST and regex lint backends. Each language has two lint implementations: tree-sitter AST (accurate, default) and regex (lightweight fallback). Select via parser = "regex" in .rlsbl/lint.toml.
  • Per-language lint config. Lint rules are now configured in .rlsbl/lint/python.toml, go.toml, and npm.toml with [forbidden-imports], [stdout], and [entry-point] sections. Scaffold generates these with sensible defaults. The old lint.toml ignore list is deprecated; a warning is shown if detected.
  • Built-in pre-release checks. rlsbl release now runs tests and lint automatically before releasing. No hook customization needed for standard checks. Skip with --skip-tests or --skip-lint.
  • Two-hook model. New pre-checks.sh hook runs before built-in checks (for setup tasks). The existing pre-release.sh runs after (for custom validation).
  • Standalone library lint. rlsbl doctor --check library-lint now works on any project, not just monorepo libraries.

#Fixes

  • Fix: lint false positives from vendored code. The lint file walker no longer descends into .venv/, node_modules/, __pycache__/, and other non-source directories.

#0.22.1

#Features

  • Name check short-circuiting. When a name is already taken, variant checking and GitHub repo lookups are now skipped, reducing API calls from 6 to 1-2 per taken name. Ultranormalization breaks after the first conflict instead of checking all 64 variants.
  • Reason-specific explanations. Check results now explain WHY a name was rejected: stdlib module conflict, npm moniker collision, or visual similarity. Previously only the status ("taken") was shown.
  • PyPI caveats for available names. Available PyPI names now always show the prohibited names list warning and suggest --ultranormalized-variants when the flag wasn't used.
  • Steps-run summary. Verbose check output ends with a "Checked:" line listing which validations ran (registry, stdlib, variants, GitHub, ultranormalization, moniker similarity).
  • Multi-name summary. Batch checks now print an aggregate summary ("N available, M taken") and the delay setting after the table.
  • Rate limit retry visibility. HTTP 429 retries now print "Rate limited, retrying in Ns..." to stderr instead of sleeping silently.

#0.22.0

#Features

  • Library boundary lint. Tag monorepo projects with library = true in workspace.toml (or monorepo add --library true) to enforce library discipline. rlsbl doctor --check library-lint detects forbidden imports (argparse, flask, click, etc.), print() calls, and CLI entry points in library source files via Python AST analysis. Logging usage is flagged as a warning. Violations block releases via the pre-release hook. Supports .rlsbl/lint.toml ignore lists for false positives.
  • **Library column in monorepo status.** Shows which projects are tagged as libraries. Dynamic column — hidden when no projects have library = true.
  • PyPI check: Simple API. Switched from the JSON API to the Simple API for availability checks. Fixes false "available" results for package names that are registered but have no releases.
  • PyPI check: stdlib collision detection. Names that conflict with Python standard library modules (like queue, json, os) are now reported as taken without hitting the network.
  • **PyPI check: --ultranormalized-variants.** New flag that generates visual-similarity variants (l/1/i and o/0 substitutions) and checks each against PyPI. Catches names like cli that PyPI rejects due to collision with cl1.
  • npm check: moniker similarity detection. The npm check now queries the search API to detect moniker conflicts — names that npm considers identical after stripping punctuation. Catches cases like selfdoc conflicting with self-doc.
  • **rlsbl doctor --check <name>.** Run a single diagnostic check by name instead of all checks. Useful in CI and pre-release hooks.

#Fixes

  • Fix: scaffold template variable resolution for secondary targets. Multi-target projects (e.g., pypi+npm) no longer leave {{registryUrl}} unresolved when npm is a secondary target.

#0.21.2

#Features

  • Hook output is now visible. Pre-release and post-release hooks stream stdout/stderr to the terminal in real-time. On failure, the actual exit code is shown instead of a generic error message.
  • **RLSBL_HOOK_TIMEOUT environment variable.** Configure a timeout in seconds for release hooks. Default is no timeout (hooks run to completion), fixing the previous 120-second hard limit that silently killed long-running test suites.

#0.21.1

#Features

  • **rlsbl release --allow-dirty.** Release with uncommitted changes in the working tree. Pre-existing dirty files are tracked and excluded from the unexpected-files safety check, so genuinely new unexpected files are still caught.
  • **monorepo add passes --target to scaffold.** When an explicit target is specified (e.g., --target plain), it is forwarded to the scaffold subprocess instead of relying on auto-detection. Removes a special case where monorepo add pre-created a VERSION file for plain targets.

#0.21.0

#Features

  • **Cross-registry depends_on in workspace.toml.** Monorepo projects can now declare explicit dependencies on siblings in any ecosystem: depends_on = ["framework"]. These edges are respected by release-order, counted in status Deps/Rdeps columns, and shown in outdated with status "explicit". Use monorepo add --depends-on name1,name2 to set them during project registration.
  • **plain target for no-build-system projects.** Register template directories, shared config, or other non-code projects with monorepo add --target plain. Uses a plain VERSION file, creates GitHub Releases with changelog notes, but generates no CI or publish workflows. Standard tag format.
  • **--target flag on monorepo add.** Explicitly specify any target type, bypassing auto-detection. Works for all registered targets, not just plain.
  • Reusable npm binary wrapper. The platform-specific npm package distribution pattern (esbuild/biome/turbo-style) is now a shared module used by both Go and Zig targets. Platform list is configurable via npm_wrapper.platforms in project config.
  • Zig target. New release target for Zig projects. Detects build.zig.zon, manages versions via VERSION file with best-effort .zon sync, generates CI (via mlugg/setup-zig) and publish workflows that cross-compile for 6 platforms from a single runner. Supports optional npm binary wrapper distribution.
  • CI router fix for projects without workflows. monorepo sync no longer includes projects without CI workflows in the CI router, preventing references to non-existent workflow files.

#0.20.0

#Breaking

  • **Breaking: rlsbl check now requires --target.** The implicit default of checking both npm and PyPI has been removed. Specify --target npm, --target pypi, or --target go explicitly.

#Features

  • Multi-name checking. rlsbl check foo bar baz --target pypi checks multiple names in one invocation and prints a compact table. Single-name invocations still show the verbose format with variants.
  • **Rate limiting for rlsbl check.** New --delay flag (default 200ms) throttles between names. HTTP 429 responses from PyPI/Go/GitHub trigger automatic retry with exponential backoff.
  • **rlsbl monorepo check-names.** Batch-check name availability for all workspace projects. Supports --prefix and --suffix to evaluate namespacing strategies (e.g., --prefix www- --target pypi).
  • **rlsbl monorepo outdated.** For each project, shows its intra-workspace dependency constraints against current sibling versions. Reports versioned deps as ok/outdated, and labels workspace/path references.
  • **Dependency columns in rlsbl monorepo status.** New Deps and Rdeps columns show how many workspace siblings each project depends on and how many depend on it. Hidden when no intra-workspace dependencies exist.
  • Monorepo-aware pre-push changelog check. The pre-push hook now detects monorepo context and only checks changelogs for projects whose files appear in the pushed commits.
  • **Per-subcommand help for rlsbl monorepo.** Each subcommand now has its own --help with usage and description.
  • Path dependency rewriting for PyPI. When building a PyPI package in a monorepo, path dependencies (e.g., core @ {root:uri}/../core) are automatically rewritten to versioned constraints in a temp copy. The working tree is never modified.
  • **rlsbl monorepo release-order.** Shows the topological order to release projects in, based on intra-workspace dependencies. Detects cycles.

#0.19.1

  • No user-facing changes.

#0.19.0

#Features

  • **rlsbl deploy [name] command.** Deploy to configured targets via SSH with health checks (HTTP, TCP, script) and automatic rollback on failure. Configure targets in .rlsbl/config.json under the deploy key. Supports --dry-run to preview without executing and --force to override branch restrictions.
  • Deploy CI workflow template. rlsbl scaffold generates a deploy workflow when deploy targets are configured.
  • Project root discovery. rlsbl now finds the project root automatically, so commands work from any subdirectory (like git, cargo, npm).
  • Scaffold untracks gitignored files. rlsbl scaffold runs git rm --cached on tracked files matching new .gitignore entries.
  • **Monorepo: lock files moved to .rlsbl-monorepo/.** rlsbl release no longer creates a spurious .rlsbl/ directory at the repo root.
  • Deploy after publish. rlsbl release runs deploy automatically after publish completes. Deploy failures do not undo the release — retry with rlsbl deploy <name>.

#0.18.1

#Features

  • **env_file config key.** Set "env_file": "~/path/to/.env" in .rlsbl/config.json to load environment variables before release. Useful for secrets needed by target publish steps (e.g., CLOUDFLARE_API_TOKEN for docs deploys).

#0.18.0

#Breaking

  • **Breaking: removed --include and --exclude flags from rlsbl release.** Target selection for releases is now config-only via release_targets in .rlsbl/config.json.

#Features

  • Go binary distribution: Homebrew tap. Go binary projects can now scaffold Homebrew tap support. Set {"homebrew": {"tap": "homebrew-tap"}} in .rlsbl/config.json to add a brews: section to the goreleaser config and pass HOMEBREW_TAP_TOKEN to the publish workflow. Users install via brew install user/tap/tool.
  • Go binary distribution: npm wrapper. Go binary projects can scaffold npm binary wrapper packages (the esbuild/biome/turbo pattern). Set {"npm_wrapper": {"scope": "@user"}} to generate platform-specific packages for 6 platforms (linux/darwin/win32, x64/arm64), a wrapper package with optionalDependencies, a bin script, and a publish workflow that packages goreleaser archives into npm packages. Users install via npm install -g @user/tool.

#0.17.0

#Features

  • Cross-target metadata in templates. Multi-target projects now merge template variables from all targets during scaffold, not just the primary. Variables are namespaced by target ({{pypi.minRequiredPython}}, {{npm.minRequiredNode}}). CI templates include runtime version references from project manifests (requires-python, engines.node, go directive, rust-version).
  • **rlsbl doctor: metadata consistency checks.** Three new checks validate that package name, license, and description are consistent across targets. Names are normalized per registry conventions (npm scope stripping, PyPI PEP 503, Go module path). Mismatches produce warnings, not failures.
  • Per-target subdirectory paths. Targets can now live in subdirectories. Configure with {"name": "npm", "path": "npm/"} in the targets array (plain strings still default to project root). Version sync, build, publish, doctor, status, and scaffold all resolve per-target paths. Useful for projects that ship wrapper packages alongside the main artifact.

#0.16.1

#Features

  • npm scaffold: lockfile warning. rlsbl scaffold now warns when an npm project has no lockfile (package-lock.json, pnpm-lock.yaml, or yarn.lock) and adds a "run npm install" step to the next steps output. Prevents broken CI from npm ci failing on first push.

#0.16.0

#Features

  • **rlsbl doctor command.** Diagnoses release state with 7 checks: stale lock file, version consistency across targets, local/remote tag existence, GitHub Release existence, branch sync, changelog coverage. --fix auto-repairs safe issues (stale locks, missing remote tags, missing GitHub Releases).
  • Lock file hardening. .rlsbl/lock added to gitignore template. atexit handler ensures lock cleanup on process exit. New is_stale() helper for doctor.
  • Go scaffold: goreleaser ldflags. Goreleaser template now includes -X main.version={{.Version}} for version injection at build time.
  • Go scaffold: dynamic goreleaser main field. main: field auto-detects root vs cmd/<name>/ project structure via {{goreleaserMain}} template variable.
  • Go scaffold: version.go generation. Binary Go projects get a scaffolded version.go with ReadBuildInfo fallback for go install users. Libraries are excluded.
  • npm: package manager detection. NpmTarget detects pnpm, yarn, or npm by searching for lock files from the project directory up to the git root.
  • npm: per-manager CI and publish templates. Separate CI and publish workflow templates for npm, pnpm, and yarn. pnpm templates include pnpm/action-setup@v4. All CI templates now include an install step before testing.

#0.15.0

#Features

  • Deleted built-in config migration engine. Removed rlsbl/lib/ (ConfigMigrator, schema_loader, ~440 LOC), the rlsbl config subcommand tree, and all associated tests (~1,500 LOC). Config migrations are now handled by the external migrable tool.
  • **rlsbl migrate command.** Shells out to migrable migrate --config-dir .rlsbl. Supports --dry-run and --status. Gives install instructions if migrable is not found.
  • **--json flag for rlsbl status.** Outputs structured JSON with name, version, target, branch, tag, clean, changelog, ci, publish.
  • Documented hidden flags. --no-commit and --skip-shared now appear in rlsbl scaffold --help.
  • Go root main detection. rlsbl scaffold warns when a Go project has its main package in cmd/<name>/ instead of the project root, since go install module@latest won't work.

#0.14.0

#Features

  • Router watch paths. Projects in a monorepo can declare extra file patterns to watch via --watch on monorepo add or the watch key in workspace.toml. The CI router generates multi-line path filters including both the project directory and all watch entries.
  • Swift target split. New swift-apple target for Apple-platform Swift projects (macOS-only CI). The existing swift target keeps macOS+ubuntu for server-side Swift. swift-apple requires explicit declaration in .rlsbl/config.json (no auto-detection).
  • Subtree publishing. Monorepo projects with subtree_remote configured get automatic git subtree pushes after release. The project's subdirectory is split and pushed to a mirror repo with plain semver tags, enabling SPM consumption. A GitHub Release is also created on the mirror. Failures are non-fatal.
  • Explicit target enforcement. rlsbl scaffold now warns when using auto-detected targets and always writes the detected target to .rlsbl/config.json, ensuring subsequent runs use explicit config.
  • **monorepo status enhanced.** Optional Watch column (path count) and Remote column (subtree URL) appear when projects use these features.
  • **monorepo sync warns for Swift projects** without subtree_remote, since SPM can't resolve monorepo-style prefixed tags.
  • 12 registered targets. swift-apple joins npm, pypi, go, swift, cargo, deno, docker, hex, maven, spec, docs.

#0.13.1

#Features

  • **Monorepo sync adds working-directory.** Synced CI workflows now include defaults: run: working-directory: {path} so steps run in the correct project subdirectory.
  • Monorepo add shows guidance. When no target is detected, the error now suggests which manifest files to create.
  • Dynamic merged publish workflows. Multi-target projects now get dynamically generated publish workflows composed from each target's individual template. Supports all 11 targets, replaces the static npm+pypi+go-only merged template.

#0.13.0

#Features

  • Monorepo support. New rlsbl monorepo command family for managing multi-project repos with independent versioning. Projects remain fully standalone — extracting to a solo repo requires zero config changes. - monorepo init creates a .rlsbl-monorepo/workspace.toml workspace manifest. - monorepo add <path> registers a project (auto-detects target, auto-scaffolds, auto-syncs CI). - monorepo remove <path> unregisters a project. - monorepo list shows all registered projects. - monorepo status shows version, latest tag, target, and unreleased changelog entries per project. - monorepo sync copies per-project CI workflows to root, rewrites triggers to workflow_call, generates a CI router (paths-filter dispatch) and publish router (tag-prefix dispatch), sets copies read-only with source header.
  • Scoped releases in monorepos. rlsbl release inside a monorepo project automatically prefixes tags ([email protected]), scopes version reads/writes and changelog to the project subdirectory, and uses a scoped commit message.
  • **Monorepo-aware rlsbl status.** Shows monorepo tag format and project count hint when inside a monorepo project.
  • Scaffold triggers monorepo sync. Running rlsbl scaffold inside a monorepo project automatically syncs workflows to root.

#0.12.0

#Features

  • 7 new release targets. swift (SPM), cargo (Rust/crates.io), deno (JSR), hex (Elixir/hex.pm), maven (Gradle/Maven), docker, spec (versioned specifications). Each with CI/publish templates and hybrid publish support.
  • Opt-in target config. Projects declare targets in .rlsbl/config.json "targets" array. Auto-detection remains as fallback for existing projects.
  • Hybrid publish. rlsbl release publishes locally when ecosystem token is available (NPM_TOKEN, CARGO_REGISTRY_TOKEN, HEX_API_KEY, etc.). Falls back to CI otherwise.
  • Private registry workflow. rlsbl scaffold --private (or auto-detected) skips publish.yml, generates a post-release hook that uploads artifacts to GitHub Releases. Prints consumer install instructions.
  • tomlkit replaces TOML regex. pyproject.toml editing (version bumps, keyword injection) now uses tomlkit for correct round-trip editing with comment preservation. Fixes edge cases with [project.urls] sub-tables.
  • detect_targets() covers all targets. Auto-detection now finds all 11 registered targets, not just npm/pypi/go.

#0.11.3

#Features

  • **--include/--exclude release flags.** Control which targets run during release. Replaces --skip-docs.
  • **release_targets config.** Declare baseline targets in .rlsbl/config.json to avoid auto-detect surprises.

#0.11.2

#Features

  • Watch re-polls for late-starting workflows. After initial runs complete, waits 5 seconds and re-polls for workflows that started late (e.g., Publish triggered by GitHub Release creation). Fixes missing Publish detection.

#0.11.1

#Features

  • Release aborts if behind remote. Fetches origin before releasing and exits if local branch is behind. Use --skip-remote-check for offline releases.
  • Watch reports which workflows ran. After CI completes, prints a summary table of workflow names and results. Warns if a publish workflow exists on disk but didn't trigger.

#0.11.0

#Features

  • Docs system extracted to selfdoc. rlsbl docs commands removed. DocsTarget now detects selfdoc.json and delegates to the selfdoc CLI. Install selfdoc separately for documentation generation.
  • **rlsbl check includes GitHub repo search.** Shows repo count as informational context (not an availability check) after registry checks.
  • Codehome target removed. The plugin target and rlsbl register command were premature and have been removed pending a more mature design.

#0.10.1

#Features

  • Codehome target rewrite. Now root-scoped: each plugin (or plugin group) lives in its own repo with plugin.json. Standard v1.2.3 tags, no namespacing. Push is delivery.
  • **rlsbl register command.** Prints the JSON registry entry for the current plugin repo (name, repo URL, description, plugins provided).
  • Scaffold template for codehome. rlsbl scaffold --target codehome creates CI workflow that validates plugin.json.
  • Plugin validation. Release validates plugin.json has required fields (name, version, description) and valid semver.

#0.10.0

#Features

  • Codehome plugin target. --target codehome --scope plugins/<name> releases individual plugins from a monorepo. Reads/writes plugin.toml, creates namespaced tags ([email protected]).
  • Docs target. Auto-generate documentation from Python docstrings and deploy to Cloudflare Pages or GitHub Pages. rlsbl docs init/build/serve/deploy commands. Zero external dependencies (stdlib ast + built-in MD/HTML converter).
  • **rlsbl targets command.** Lists all available targets with detection status, scope type, and version file.
  • Multi-target release. Secondary root-scoped targets (e.g., docs) auto-run build+deploy during release. Use --skip-docs to opt out.
  • **--target and --scope CLI flags.** --target selects the release target explicitly. --scope restricts operations to a subdirectory for subdir-scoped targets.
  • Scoped release safety. Validates scope path exists, includes pyproject.toml in commit for plugin targets, warns when --scope is used with root-scoped targets.
  • **--registry deprecated.** Use --target instead. Prints a deprecation warning when used.

#0.9.1

#Features

  • **rlsbl config show subcommand.** Bare rlsbl config now prints help; use config show for project info.
  • Race condition parsing fix. Porcelain parser handles stripped leading whitespace correctly.

#0.9.0

#Features

  • **rlsbl unreleased command.** Lists commits since last tag, cross-references CHANGELOG entries, reports coverage status. Supports --json for machine-readable output.
  • **rlsbl prs command.** Lists open GitHub pull requests for the current repo.
  • Config management system. rlsbl config init/migrate/status subcommands for managing project config with schema-driven migration (deep merge, flat merge, list-by-key merge strategies, versioned migrations, atomic writes).
  • Scaffold auto-commits. Created files are committed automatically (use --no-commit to opt out). Runs config migrations when .rlsbl/config-schema.json exists.
  • Parallel watch. rlsbl watch polls CI runs concurrently (total time = max of all runs, not sum).
  • Parallel variant checking. rlsbl check uses ThreadPoolExecutor for concurrent registry queries.
  • Advisory lockfile. .rlsbl/lock prevents concurrent release/scaffold operations.
  • **rlsbl undo improvements.** Auto-pushes revert commit (with confirmation prompt, or automatic with --yes). Prints structured failure summary table with remediation commands on partial failure.
  • Pre-release suffix support. bump_version handles versions like 1.0.0-beta.1.
  • **--force no longer overwrites user-owned files.** CHANGELOG.md, LICENSE, and hooks are preserved even with --force.
  • **Pre-release hook receives RLSBL_VERSION.** Matches the existing post-release hook behavior.
  • Release race condition fix. Aborts if unexpected files are modified before commit.
  • Top-level error handler sanitized. No longer exposes sensitive CalledProcessError details.
  • Discover hardened. Pagination capped at 20 pages; retries once on HTTP 403 with Retry-After header.
  • **record-gif validates flags.** Clear error message on non-integer flag values.
  • Release prompt mentions ecosystem tagging when enabled.
  • npm check timeout. Variant checking has 10-second subprocess timeout.

#0.8.3

#Features

  • Pre-release hook runs Python checks before npm (faster failure)
  • Go CI template uses go-version-file: go.mod instead of hardcoded versions; adds -race flag
  • Node.js 24 in all CI/publish templates (dropped Node 18 EOL)

#Fixes

  • Fix watch: resolve short SHAs to full 40-char (gh run list --commit requires it)

#0.8.2

#Features

  • Handle KeyboardInterrupt in watch command (clean exit, no stack trace)
  • Escape AppleScript strings in watch notifications (prevents injection via git tags)
  • Clear error when --registry is missing a value
  • Resolve project config path at call time (not module import time)
  • Add --width, --height, --font-size, --duration flags to record-gif

#0.8.1

#Features

  • Templates included in wheel. Moved templates/ into the rlsbl/ package so non-editable installs (pip, pipx) get them. Previously rlsbl scaffold crashed on PyPI installs.
  • **undo checks prerequisites.** Now verifies gh CLI auth and clean working tree before proceeding.
  • TOML trailing comma fix. Adding the rlsbl keyword no longer produces a double comma.
  • **Pagination URL validation in discover.** Only follows Link header URLs pointing to api.github.com.
  • **.rlsbl/version included in release commit.** No more orphaned version marker changes.
  • Non-ASCII preserved in package.json. json.dumps now uses ensure_ascii=False.

#0.8.0

#Features

  • Universal three-way merge for scaffold updates. Replaced all format-specific merge strategies (YAML job-level, JSON deep-merge, line-based, section append) with git merge-file. Bases are stored in .rlsbl/bases/ at scaffold time. On --update, user customizations and template updates merge cleanly; conflicts get git-style conflict markers.
  • **Removed ruamel-yaml dependency.** No longer needed since YAML-aware merging is replaced by three-way text merge.
  • Detailed scaffold output. Every file now shows its action: created, updated, merged, unchanged, user-owned, or CONFLICTS.

#0.7.0

#Features

  • **Removed check-prs command.** Was a useless wrapper around gh pr list.
  • **JSON deep-merge for .claude/settings.json.** Scaffold now merges new template keys into existing user settings instead of skipping the file. User values are preserved.
  • YAML job-level merge for CI workflows. ci.yml and publish.yml are now merged at the job level: rlsbl-managed jobs are updated, user-added jobs are preserved. Uses ruamel.yaml for comment-preserving round-trip parsing.
  • Explicit USER_OWNED category. CHANGELOG.md, LICENSE, and hooks are formally marked as user-owned and never overwritten.
  • LICENSE year update. scaffold --update extends the copyright year range to the current year.

#0.6.0

#Features

  • Scripts moved to subcommands. check-prs.sh, record-gif.sh, and pre-push-hook.sh are no longer scaffolded into scripts/. They are now built-in subcommands: rlsbl record-gif, rlsbl pre-push-check.
  • **rlsbl watch command.** Monitors all CI runs for a commit, prints results to stderr, sends desktop notification, exits 1 on failure. rlsbl release prints Watch CI: rlsbl watch <sha> for easy invocation.
  • Removed built-in background CI watcher from rlsbl release. Use rlsbl watch explicitly instead.
  • **Hooks moved to .rlsbl/hooks/.** pre-release.sh and post-release.sh moved from scripts/ to .rlsbl/hooks/. rlsbl release looks for hooks there.
  • Pre-push hook is a one-liner. .git/hooks/pre-push now calls exec rlsbl pre-push-check "$@" instead of being a full script copy. Updates happen via uv tool upgrade rlsbl, not re-scaffolding.

#0.5.2

#Features

  • Version detection reads source tree first. __version__ now reads pyproject.toml directly when running from source, fixing stale metadata from editable installs.
  • CLAUDE.md template is registry-specific. Publish setup instructions (NPM_TOKEN, Trusted Publishing, GoReleaser) now match the project's registry instead of always showing NPM_TOKEN.
  • Gitignore merge normalizes trailing slashes. *.egg-info/ and *.egg-info are now recognized as duplicates during scaffold merge.
  • **record-gif.sh no longer hardcodes /tmp/.** Uses bare mktemp for portability.
  • **Go check hidden by default in rlsbl check.** Only shown with --registry go. Labels changed from "available"/"taken" to "not found"/"exists" since Go modules use repository paths.
  • **Auth hint on 403 in rlsbl discover.** Suggests gh auth login when rate-limited.

#0.5.1

#Features

  • CI watcher prints to stderr. The background CI watcher now writes results to inherited stderr instead of attempting tty detection. AI agents and terminal users both see CI pass/fail in their output stream. On failure, the GitHub Actions run URL is printed.
  • ***.local-only gitignore pattern.** Scaffolded .gitignore now includes *.local-only. Use a .local-only/ directory or *.local-only suffix to keep files out of version control without per-file gitignore entries.

#0.5.0

#Features

  • Post-release hooks. scripts/post-release.sh runs after a successful release with RLSBL_VERSION env var set. Non-fatal (release is already complete). Scaffolded via rlsbl scaffold.
  • CI watcher. After pushing, rlsbl spawns a background process that watches CI via gh run watch and sends a desktop notification (notify-send on Linux, osascript on macOS) when CI passes or fails.
  • Ecosystem discoverability: rlsbl discover command lists all rlsbl-tagged projects via GitHub topics
  • rlsbl config shows ecosystem tagging status and source
  • --quiet flag is respected by all tagging output
  • Auto-tagging: scaffold and release inject "rlsbl" keyword into package.json/pyproject.toml and add the rlsbl GitHub topic
  • Opt-out via --no-tag flag, project config (.rlsbl/config.json), or user config (~/.rlsbl/config.json)
  • rlsbl discover --mine filters to the authenticated user's repos

#0.4.2

#Features

  • Configurable push timeout via RLSBL_PUSH_TIMEOUT env var (default 120s), fixing timeouts on repos with slow pre-push hooks
  • Print a note when RLSBL_PUSH_TIMEOUT overrides the default

#Fixes

  • Fix own pre-push hook missing VERSION file detection for Go projects

#0.4.1

#Features

  • Go adapter uses VERSION file as version source (not git tags)
  • First release bootstraps from VERSION without bumping
  • Pre-release.sh template auto-detects Go/npm/Python and runs appropriate checks
  • Pre-push hook template supports Go VERSION file
  • GoReleaser NEXT_STEPS clarified (CI handles it, no local install needed)

#0.4.0

#Features

  • Go project support: scaffold with GoReleaser, CI, and publish workflows
  • Version-file-less registries: release skips commit step when version is the git tag
  • Go name availability check via pkg.go.dev
  • Cross-compilation template (linux/darwin/windows x amd64/arm64)

#0.3.1

  • No user-facing changes.

#0.3.0

#Features

  • Confirmation prompt on release (skip with --yes)
  • config command: show detected registries, scaffolding state, workflows, hooks
  • undo command: revert a botched release (deletes tag, reverts commit, deletes GitHub Release)
  • Merged publish workflow for dual-registry projects (scaffold generates one file with both npm + pypi jobs)

#0.2.0

#Features

  • CLI redesign: --registry flag replaces positional registry argument
  • Rename check-name command to check
  • All commands are top-level: rlsbl release, rlsbl check, rlsbl scaffold, rlsbl status

#Fixes

  • Fix astral-sh/setup-uv version (v7, not v8)

#0.1.1

#Fixes

  • Fix astral-sh/setup-uv version (v8 tag doesn't exist, use v7)

#0.1.0

#Features

  • 4 top-level commands: release, status, scaffold, check-name
  • Initial release as rlsbl (renamed from share-it-on)
  • Pure Python (stdlib only, Python 3.11+, tomllib for TOML parsing)
  • Auto-detects registries from project files (package.json, pyproject.toml)
  • Release syncs version across all detected version files
  • Context-aware scaffold: appends CLAUDE.md, merges .gitignore, preserves custom CI
  • Hash-based --update mode detects customized files
  • Pre-release hook, pre-push changelog enforcement
  • Dual-publish CI: npm (token) + PyPI (OIDC Trusted Publishing)
  • Also installable via npm (thin Node wrapper)