Skip to content
rlsbl.external_checks
On this page

External check providers: subprocess checks with a mandatory kind -- freeform runs a shell command, structured composes argv for known tools like mypy.

#rlsbl.external_checks

#rlsbl.external_checks

External check providers: config-declared subprocess checks.

Projects declare external checks in .rlsbl/config.json under the external_checks key. Every entry declares kind = "freeform": an opaque shell command. rlsbl does not understand its scope -- the command runs verbatim through a shell.

The mandatory kind marker exists so that unmanaged scope (a freeform shell command whose target directories rlsbl cannot see) is always a visible, deliberate declaration rather than an accident.

kind = "structured" is RETIRED. It named a known tool plus a path list and had rlsbl compose the argv; that invocation shape is now three built-in checks (lint, format, type-check) configured under the top-level checks key -- see :mod:rlsbl.tool_checks. A config that still declares it is a hard error naming the replacement.

External checks are registered via a strictcli check provider (app.register_check_provider). The provider reads the project config at materialization time (keyed on cwd) and returns a list of check specs. strictcli handles memoization and re-materialization when the cwd changes.

#ExternalCheckError

Raised when external check config is invalid.

#_retired_structured_message

python
def _retired_structured_message(index, entry)

The hard error a retired kind = "structured" entry gets.

#validate_external_checks

python
def validate_external_checks(config, *, project_root=None)

Validate the external_checks section of a project config.

Every entry must declare kind = "freeform" plus name, tag and command; depends_on and cwd are optional. Any unrecognized key is a hard error, and so is the retired kind = "structured" (the message names the built-in check that replaced it).

Binary existence is validated eagerly, at registration time: the command's first token must resolve on PATH or at an absolute path.

Returns the validated list of external check dicts, or an empty list if the key is absent.

#_validate_freeform_entry

python
def _validate_freeform_entry(i, entry)

Validate the command field of a freeform entry and probe its binary.

#_make_external_check_fn

python
def _make_external_check_fn(command, cwd, name)

Build a check function that runs a freeform command through a shell.

The returned function has the (ctx, reporter) signature expected by strictcli's check system. The timeout is resolved per run from the live context (see :func:_resolve_check_budget). The subprocess env carries the release context (see :func:_release_context_env).

#_entry_specs

python
def _entry_specs(entry)

Build the check spec for a single validated external-check entry.

One impure subprocess check per entry. No timeout is bound here: the budget is resolved per run from the live check context (see :func:resolve_check_budget).

#make_external_check_provider

python
def make_external_check_provider(config_reader)

Build a check provider that reads external checks from config.

config_reader is a callable that returns the project config dict for the current working directory. The provider is called lazily by strictcli at materialization time (memoized by cwd).

Returns a provider function suitable for app.register_check_provider().

#run_external_preflight_checks

python
def run_external_preflight_checks(app, ctx, config, *, tag_expr='preflight', pure_only=False)

Run ONLY the config-declared external checks matching tag_expr.

Used when the pre-release hook is customized: built-in preflight checks (test-suite, lint, maven-central-metadata) are the hook's responsibility and must be skipped, but config-declared external checks must still run.

Selection mechanism: each external check is selected by its exact name intersected with tag_expr (strictcli's run_checks ANDs name_glob with tag_expr). This runs exactly the config-declared external checks that carry the preflight tag and never selects a built-in check.

pure_only is the rehearsal's partition, and it is what makes this entry point usable under --dry-run: pure checks EXECUTE and report real findings, while impure ones are listed rather than run. The non-customized-hook branch has always previewed that way; passing this through is what stops the customized-hook branch from being the one place a preview silently skips a check it could have run.

The check provider must have already been registered on app (via app.register_check_provider).

Returns (results, impure_listed, exit_code): the executed checks, the names withheld by the purity partition (empty unless pure_only), and a non-zero exit code if any executed check failed.

More tools from this site

  • claudestream Drive Claude Code from Python: run it as a subprocess and read its output as typed events, with async and sync sessions, sandbox policies, and tools you define in Python
  • claudewheel A TUI Claude Code Launcher that lets you have more than one profile, manage sessions lifecycle, pick the exact CC version, model to use (even older unlisted ones), pick which GitHub account to use, etc.
  • dirstat Fast, single-binary directory statistics CLI: every file under a tree grouped by format, with counts, sizes, and lines of code, as a colored terminal table or as JSON
  • fastware A batteries-included ASGI framework: msgspec JSON, a managed Granian server, dependency injection, SSE, WebSockets, auth, and a test client
  • go-toml-edit Zero-dep TOML editing library for Go with comment preservation
  • howmuchleft The fastest Claude Code statusline: context window, 5-hour, and weekly limit usage as three customizable gradient bars, rendering in about 6 ms
  • orxtra
  • pgdesign
  • predraw Declarative rendering pipeline: describe a scene in JSON and get SVG, PNG and WebP out, with light and dark style tokens, reusable components and text converted to path outlines
  • reposummary Turn a git repository's history into a Markdown journal: pick a time window or revision range and get a readable digest of what changed, optionally narrated by an LLM
  • safegit git wrapper CLI that gives each commit its own temporary index and retries ref updates on conflict, so concurrent agents share one repository
  • saferm Command-line replacement for rm that archives every deletion with a mandatory reason and the context it ran in, so deleted files can be listed, inspected and restored
  • selfdoc Static Site Generator that builds a project's documentation site directly from its source code, so the docs can never drift from the code they describe, with SEO/AEO, first-class blog, search, and cross-project linking built in
  • strictcli
  • stricttest An always-on test-isolation floor: a pytest plugin and a Go env-hygiene module that make a test suite structurally unable to reach real credentials, the real HOME, the network, or the development repository.
  • wesktop A Python framework that turns an ASGI web app into a desktop application, serving it from a local Granian server and displaying it in a native OS window via pywebview
Search