ADR-028: Collection styles are configuration; the changelog shape is one of them

Status Active · Filed 2026-08-04 · Influenced by ADR-002 · ADR-012

Context

The collector was built for the devlog and said so (ADR-012): a narrative log has no categories and no release cadence, so collection was “append these bodies, oldest first, at the marker”, and a changelog that wanted more was scriv’s problem — “the two coexist because the fragment convention is the contract, not the collector” (ADR-002).

strata-g took that trade and is now unwinding it: with the rest of its doc machinery on Luria, scriv is the last foreign moving part, kept for exactly one property — a changelog reads newest-first, and the append style would bury the latest batch at the bottom of the file. The fragment convention was already shared; only the assembled shape differed.

Decision

The shape is declared on the fragment mapping:

[luria.fragments."record/changelog.d"]
file  = "CHANGELOG.md"
style = "changelog"
  • append (default, unchanged): bodies oldest-first, inserted before the marker; the marker stays at the end of the file.
  • changelog: one batch per collection under a ## <date> heading, inserted immediately after the marker, so batches stack newest-first; within a batch, fragments read newest-first too. A batch containing only stub fragments emits nothing — no date heading with nothing under it, which under scriv was a documented caveat someone had to revert by hand.

A string value still means the append style, so no existing configuration changes meaning. Luria’s own changelog switches to the new style — the marker was already positioned after the header, which is where a changelog-style marker belongs.

What the style deliberately does not add is scriv’s category merging: a fragment carries its own ### Added/### Fixed sections and the batch keeps them per-contribution. Merging categories across fragments earns its complexity in a versioned-release changelog; a per-merge project log reads fine — arguably better — with each contribution’s sections intact.

Alternatives considered

  • Keep delegating changelogs to scriv. Defensible when scriv was one of several tools; as the last one standing it made “the project memory machinery” a two-package install for one insertion order.
  • Infer the order from the marker’s position (top of file → newest first). Silent, and wrong the day someone reorganises a header; a declared style fails loudly instead (DP-1).
  • Reproduce scriv (categories, versions) inside the collector. The complexity serves release management, which Luria does not do; projects that want it can still point the directory at scriv — that escape hatch is unchanged.
  • Newest-first as an order flag rather than a style. The dated batch heading and the stub rule travel with the reading order in every real case; three flags that only ever move together are one style wearing three names.

Consequences

  • strata-g’s changelog collects with luria collect and scriv retires there; the weekly workflow loses its pip install scriv.
  • The batch date is collection day, as it was under scriv — the fragments’ own commit dates order them within the batch but do not label it.
  • collect() stays pure (text + bodies + style + date in, text out); the CLI supplies today’s date at the one call site.
  • A second consumer of the changelog style with a different heading want (version numbers, say) motivates a template key on the fragment mapping; it is not speculated into existence now.