app.domain.records¶
ADR record parsing, validation, title/date derivation and identity.
parse_record() turns the raw bytes of one Markdown ADR file into a
ParsedRecord. It never raises for content problems: every
problem becomes an Issue and the record stays
storable and browseable.
Field handling (see docs/developer/domain/schema.rst):
uuid– required; canonical hyphenated UUID. Without a valid UUID the record is keyed by its source location (record_key()), its outbound relationships are disabled and it cannot be approved.title– optional; fallback to the first Markdown H1, then to the humanised filename slug (ParsedRecord.title_source).decision-date– optionalYYYY-MM-DD. The filename date is never substituted silently: it is exposed asParsedRecord.inferred_dateand flagged byParsedRecord.decision_date_inferred.erratum-for– makes the document an erratum of the decision with that UUID (stored as the internalcorrectslink). Errata also usetype(required),section,reported-byanddate(the report date, exposed likedecision-date), and their body is parsed intoParsedRecord.erratum(app.domain.errata). Without an explicittitlean erratum is titled “Erratum: <section>”, else “Erratum: <humanised filename slug>”.kind/corrects– the retired erratum shape; rejected withlegacy_erratum_formatand the file is treated as a decision.updates/obsoletes– lists of UUIDs.deprecates– legacy alias merged intoobsoletes(warning).signed-off-by– legacy, exposed asParsedRecord.legacy_signofffor display as “Legacy sign-off (unverified)”; it never implies approval.
The value types and helpers live in app.domain.values,
app.domain.titles and app.domain.validation; this module
re-exports them so callers need a single import.
Public API:
ADR_FILENAME_RE,KNOWN_FIELDSRecordKind,TitleSource,LinkType,Links,Identity,ParsedRecordis_adr_filename(),filename_date(),derive_title(),record_key(),parse_record()
- class app.domain.records.ErratumContent(type, section, reported_by, reported_date, original, corrected, notes)¶
Bases:
objectThe full content of one erratum, safe to persist.
- Parameters:
type (
ErratumType|None) – Erratum type,Noneif missing or invalid (reported asbad_erratum_type).section (
str|None) – Where in the decision the error is, if given.reported_by (
str|None) – Free-text reporter; informational only.reported_date (
date|None) – Authored report date, if valid.original (
str|None) – Markdown of the “Original text” section, if any.corrected (
str) – Markdown of the “Corrected text” section; empty when missing (reported aserratum_missing_corrected_text).notes (
str|None) – Markdown of the notes, including unrecognised content.
- type: ErratumType | None¶
- to_dict()¶
Convert to a JSON-serialisable mapping.
- class app.domain.records.ErratumType(*values)¶
Bases:
StrEnumKind of correction an erratum reports.
- TECHNICAL = 'technical'¶
- EDITORIAL = 'editorial'¶
- class app.domain.records.Identity(source_id, project, record_key)¶
Bases:
objectLogical identity of an ADR: record key within registration + project.
- Parameters:
source_id (
str) – Source registration id.project (
str) – Owning project path.record_key (
str) – UUID string or fallback key (record_key()).
- class app.domain.records.LinkType(*values)¶
Bases:
StrEnumOutbound relationship types, named as written in frontmatter.
- UPDATES = 'updates'¶
- OBSOLETES = 'obsoletes'¶
- CORRECTS = 'corrects'¶
- class app.domain.records.Links(updates=(), obsoletes=(), corrects=None)¶
Bases:
objectOutbound UUID relationships of one record.
- Parameters:
- pairs()¶
List every outbound link with its type, in a stable order.
- to_dict()¶
Convert to the JSON-serialisable shape stored in
record.links.
- class app.domain.records.ParsedRecord(body, metadata, title, title_source, decision_date, inferred_date, links, adr_uuid, legacy_signoff, issues, encoding_ok=True, erratum=None)¶
Bases:
objectResult of parsing one ADR file. All fields are safe to persist.
- Parameters:
body (
str) – Markdown body without the frontmatter block.metadata (
dict[str,JsonValue]) – Raw frontmatter as JSON-serialisable values.title (
str) – Display title.title_source (
TitleSource) – Wheretitlecame from.decision_date (
date|None) – Authoreddecision-date(datefor an erratum), if valid.inferred_date (
date|None) – Date taken from the filename, if any.links (
Links) – Validated outbound links (empty without a valid UUID).adr_uuid (
UUID|None) – Authored record UUID, orNoneif missing/invalid.legacy_signoff (
tuple[str,...]) – Unverified legacysigned-off-byvalues.issues (
tuple[Issue,...]) – Validation issues in a stable order.encoding_ok (
bool) –Falseif the bytes were not valid UTF-8.erratum (
ErratumContent|None) – Erratum content,Nonefor a decision.
- title_source: TitleSource¶
- erratum: ErratumContent | None¶
- property record_kind: RecordKind¶
Tell whether this is a decision or an erratum.
- Returns:
RecordKind.ERRATUMifferratumis set.
- property decision_date_inferred: bool¶
Tell whether the shown date is only inferred from the filename.
- Returns:
Truewhen nodecision-datewas authored but the filename carries a date.
- property display_date: date | None¶
Date to display.
Label it “inferred from filename” when
decision_date_inferredis true.- Returns:
The authored date, else the filename date, else
None.
- property has_errors: bool¶
Tell whether any issue has error severity.
- Returns:
Trueif at least one error was found.
- property approval_blocker: str | None¶
Explain why this content cannot be approved, if it cannot.
- Returns:
A reader-facing reason, or
Noneif approvable.
- class app.domain.records.RecordKind(*values)¶
Bases:
StrEnumKind of ADR record.
- DECISION = 'decision'¶
- ERRATUM = 'erratum'¶
- class app.domain.records.TitleSource(*values)¶
Bases:
StrEnumWhere the display title came from.
- FRONTMATTER = 'frontmatter'¶
- H1 = 'h1'¶
- FILENAME = 'filename'¶
- app.domain.records.derive_title(explicit, body, filename)¶
Choose the display title: frontmatter, first H1, then filename.
- app.domain.records.filename_date(name)¶
Extract the date prefix of an ADR file name.
- app.domain.records.is_adr_filename(name)¶
Tell whether a file name matches the legacy ADR discovery pattern.
- app.domain.records.parse_record(raw, *, filename)¶
Parse and validate one ADR file. Never raises for content problems.
- Parameters:
- Return type:
- Returns:
The parsed record with all issues found.
- app.domain.records.record_key(adr_uuid, source_id, project, path)¶
Compute the stable record key used in the logical identity.
- Parameters:
- Return type:
- Returns:
The lowercase UUID string, or
src:<source_id>/<project>/<path>when there is no valid UUID. A UUID is never invented.