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
def generate_entry_id() -> strGenerate 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
def _native_message(diag, entry: ChangelogEntry) -> strRender 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
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
def _gate_line(line: str) -> NoneRun 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
def parse_entry(line: str, *, enforce_format_version: bool=False) -> ChangelogEntryParse one JSON line into a ChangelogEntry.
The per-line format_version gate is routed through strictspec:
- a line carrying
format_versionis validated via strictspec (a wrong or
unsupported version is a hard error);
- a line lacking
format_versionis 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
def serialize_entry(entry: ChangelogEntry) -> strSerialize 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.
#parse_jsonl
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).