Skip to content
rlsbl.changelog.schema
On this page

JSONL changelog entry schema with dataclass definition, JSON parsing, serialization, field validation, type coercion, and entry ID generation.

#rlsbl.changelog.schema

#rlsbl.changelog.schema

JSONL changelog entry schema with dataclass definition, JSON parsing, serialization, field validation, type coercion, and entry ID generation.

The strictspec-generated validator (rlsbl/strictspec_gen/changelog_entry_commit_validator.py) is the DOCUMENT authority for one JSONL line: the per-line format_version gate and the field/enum/conditional-required shape. This module routes shape validation through it and keeps only what strictspec cannot see (hash resolution, tag ranges, coverage vs git, batch limits, cross-file rules) native -- those live in validate.py and files.py.

Transition contract (see docs/changelog.md): every line rlsbl WRITES carries format_version = 1. Reading is EXPLICIT two-mode -- a line carrying format_version is validated via strictspec; a line lacking it is legacy and accepted ONLY when the caller opts into legacy mode (enforce_format_version=False, the transition default). With enforce_format_version=True a missing gate is a hard error. The absence is never silent: a warn-level check surfaces "enforcement not yet enabled" until a repo records its changelog_format_version_enforced decision in its config.

#generate_entry_id

python
def generate_entry_id() -> str

Generate a unique entry ID.

Uses a timestamp-prefixed UUID4 hex for approximate lexicographic sortability without adding external dependencies. Format: <timestamp_hex><uuid4_hex> (48 chars total: 16 timestamp + 32 uuid).

#ChangelogEntry

One line in a .jsonl changelog file.

#_native_message

python
def _native_message(diag, entry: ChangelogEntry) -> str

Render one strictspec diagnostic as an rlsbl-native schema error string.

strictspec is the shape engine; this is a thin presentation adapter that preserves the historical rlsbl wording (which the check layer and tests read) without a second validation implementation.

#validate_schema

python
def validate_schema(entry: ChangelogEntry) -> list[str]

Return a list of schema errors for the entry. Empty list means valid.

commits is required and id is optional. The entry is serialized (stamping format_version = CURRENT_FORMAT_VERSION) and validated through the strictspec-generated validator -- the single shape engine. Diagnostics are rendered back into rlsbl's native wording by :func:_native_message.

#_gate_line

python
def _gate_line(line: str) -> None

Run the strictspec per-line format_version gate on a raw JSONL line.

Uses the validator's compiled program, but checks only the gate, never entry shape. Raises ChangelogError when format_version is present but not accepted (e.g. a future/wrong value). A line with NO format_version passes here silently -- the legacy/enforced decision is the caller's (see :func:parse_entry).

#parse_entry

python
def parse_entry(line: str, *, enforce_format_version: bool=False) -> ChangelogEntry

Parse one JSON line into a ChangelogEntry.

The per-line format_version gate is routed through strictspec:

  • a line carrying format_version is validated via strictspec (a wrong or

unsupported version is a hard error);

  • a line lacking format_version is LEGACY. It is accepted only when

enforce_format_version is False (the transition default). With enforce_format_version=True a missing gate is a hard error telling the operator to stamp the line, re-add the entry, or record a deliberate legacy-mode decision in .rlsbl/config.json.

Raises ChangelogError on malformed JSON or missing required fields. Historical entries without id load fine (id is optional on read). Entries without commits load with an empty commits list; the changelog-schema check is what rejects them.

#serialize_entry

python
def serialize_entry(entry: ChangelogEntry) -> str

Serialize a ChangelogEntry to one JSON line (no trailing newline).

Every line is stamped with format_version = CURRENT_FORMAT_VERSION as the leading key (the per-line gate). Only includes non-None optional fields to keep lines compact. Omits commits when the list is empty.

#entry_content_key

python
def entry_content_key(entry: ChangelogEntry) -> tuple

The identity of an entry that carries no id: what the entry SAYS.

id is optional on read, so a historical line has none and cannot be recognized by it. The fallback is the same identity the changelog's own consolidation dedup uses -- the commit SET plus the fields that carry meaning -- which is what makes "have I already copied this entry?" answerable for a line that predates entry ids.

The commits are a frozenset because order is not part of an entry's identity: the same commits listed in another order are the same entry.

#parse_jsonl

python
def parse_jsonl(path: str, *, enforce_format_version: bool=False) -> list[ChangelogEntry]

Read a .jsonl file and return a list of ChangelogEntry objects.

Raises ChangelogError with line number on malformed JSON. When enforce_format_version is True, a line lacking format_version is a hard error (the caller threads this from the project's changelog_format_version_enforced config -- see :func:rlsbl.changelog.files.read_changelog_format_version_enforced).

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