Skip to content
rlsbl.commands.transition_record_cmd
On this page

The command behind rlsbl transition record: which two kinds it writes, which record file it appends to, and the duplicate-declaration refusal it answers with.

#rlsbl.commands.transition_record_cmd

#rlsbl.commands.transition_record_cmd

rlsbl transition record: the typed door onto the operator-declared facts.

Most transition record events are written by the surgery that produced them -- an extract writes its conversion, a rewrite writes its commit remap, a rename writes its boundary alias. The kinds below are the ones an operator can declare instead: two that no command writes at all, because they are not things a command DID, and one whose command exists but which a hand-performed rename leaves with nothing to have recorded it.

non-version-tag This tag stands outside the version model on purpose -- a nightly marker, an upstream vendor tag imported with a history. Nothing can derive that; a human decides it, and the readers of the tag namespace (:mod:rlsbl.tag_explanation, hence rlsbl release backfill and rlsbl release reconcile) then stop reporting it forever.

release-history-closed This member's or releasable's release history is deliberately over, so the version file, changelog directory and archives it leaves behind are a record rather than residue.

releasable-rename This releasable used to be called something else. rlsbl monorepo rename-releasable records it itself, beside the boundary alias tag it creates; the door is here for a rename performed another way -- edited into workspace.toml by hand, or carried in from a repository converted before the record existed. It is a tag-SPELLING fact and never an identity change, so it does not make rlsbl release reconcile refuse anything.

Until this command existed the only way to write the first two was the Python snippet rlsbl release backfill's own refusal spelled out. A fact worth recording in a committed store is worth a typed door.

WHERE IT WRITES: the repository-scoped record -- <root>/.rlsbl-monorepo/transitions.jsonl in a workspace, and <root>/.rlsbl/transitions.jsonl in a standalone repository, which is :func:rlsbl.transition_record.repository_transition_record_path's answer and therefore exactly the file the backfill's refusal names and reads back. Every kind here goes there rather than into a releasable's own state directory: a tag namespace belongs to the repository, a releasable whose release history just closed may be a releasable whose state directory is about to leave with it, and a renamed releasable's state directory no longer exists under the OLD name -- which is the spelling a reader looking the rename up will have.

The same resolution is what :func:rlsbl.targets.refs.ref_context adds to the records the TAG-NAMESPACE question consults, so a non-version-tag declared here is seen by rlsbl release reconcile in a workspace as well as in a standalone repository.

WHAT IT REFUSES: a second declaration of the same kind about the same subject (the record is append-only, so a duplicate would stand beside the first forever with no way to say which one is meant), a --releasable-rename without the --to naming what it was renamed to, and -- defensively -- a kind outside the declared set. A rename's subject is the PAIR of names, so renaming widget to gadget and later renaming it back are two facts rather than one repeated. A supplied-but-empty subject or reason is refused one step earlier, at the CLI boundary (rlsbl._refuse_empty_flags), which is the one place in rlsbl that decides what an explicitly-empty value means, so this command's message for it is every other command's message for it. The choice flag admits only these kinds, so no argv reaches that last refusal; it exists so that widening the choice without teaching this router is a hard error rather than an event written with a shape nobody checked.

#_subject_of

python
def _subject_of(event)

The one string an event declares its fact about.

A rename is about a PAIR of names, so its subject is both: renaming widget to gadget and later renaming it back are two different facts that both concern widget, and a duplicate refusal keyed on the old name alone would refuse the second as a repeat of the first.

#run_cmd

python
def run_cmd(flags, *, ctx)

Record one operator-declared transition record fact.

Exits non-zero through :func:sys.exit on every refusal, so a failure is the process's rather than a value a caller could ignore.

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