Skip to content

feat(author): aggregate per-dataset changelog entries with category sections and ChangeItem.targets#4

Merged
aaronstevenwhite merged 2 commits into
mainfrom
feat/aggregate-changelog-entries
Jun 26, 2026
Merged

feat(author): aggregate per-dataset changelog entries with category sections and ChangeItem.targets#4
aaronstevenwhite merged 2 commits into
mainfrom
feat/aggregate-changelog-entries

Conversation

@aaronstevenwhite

Copy link
Copy Markdown
Contributor

Summary

Address #3: aggregate per-dataset changelog entries. A dataset is not one record. It fans out across many component records (corpus, expressions, segmentations, annotations, alignment, ontology), so the natural changelog unit is the dataset, not the record. This adds a generic aggregate builder that assembles one pub.layers.changelog.entry per dataset anchor from the diffs of those component records. It also cuts the 0.3.0 release. Follows from #1 (which generates one entry per changed record).

Changes

  • lairs/author/changelog.py. New ComponentChange value model (uri, collection, field_diff) and build_aggregate_entry(*, subject, subject_collection, components, previous_version=None, classifier=None, created_at=None, summary=None, targets_per_item=10). It groups components by _category_for(collection) into ChangeSections, summarises each category's changes into counted ChangeItems whose targets point at the changed components, and bumps the version once from the whole aggregate (additive -> minor, value-only -> patch, removals or identity/reference breaks -> major), monotonic from previous_version. An aggregate with no real component change does not bump and emits no sections (idempotent).
  • Scale guard. A representation change can touch 100k+ component records, more than one record can enumerate. Each item carries the true count in its description (for example "Added features to 25 ontology records") and a bounded, representative set of targets capped at targets_per_item (None omits targets). The cap is never silent: the description always reflects the full count. The codebase uses no logging, so the count-in-description is the explicit non-silent signal rather than a new logging dependency.
  • Reuse. Builds on what 0.2.x already ships: diff_record, _category_for / _CATEGORY_BY_NAMESPACE, and BumpClassifier.classify over the multi-component {uri: changes} mapping. Existing per-record build_entry / publish(changelog=True) behaviour is untouched.
  • Release 0.3.0. Bumped pyproject.toml, the _FALLBACK_VERSION literal, uv.lock, and CHANGELOG.md (new ## [0.3.0] section plus footer links).

This is pure assembly over already-computed diffs: it reads no PDS state (the caller supplies previous_version) and does not touch the read/write data flow or the generated models. Out of scope, left to the consumer (per #1): which record anchors a dataset, the record-to-subject grouping, the cross-account orchestration, the upstream version: str, and bump overrides.

Type of change

  • Bug fix (a non-breaking change that fixes an issue)
  • New feature (a non-breaking change that adds functionality)
  • Breaking change (a fix or feature that changes existing behaviour)
  • Documentation
  • Refactor, test, or chore (no user-visible change)

Checklist

  • uv run ruff format --check lairs tests passes
  • uv run ruff check lairs tests passes (including ANN401; no Any in annotations)
  • uv run ty check --error-on-warning passes
  • uv run pytest passes (1078 passed, 71 skipped)
  • uv run pytest --run-integration -m integration passes against the Docker test PDS (71 passed)
  • uv run --group docs mkdocs build --strict passes
  • Tests added or updated for new behaviour, mirrored 1:1 under tests/
  • CHANGELOG.md updated (a new ## [0.3.0] release section)
  • No @dataclass, pydantic, Any, or object annotation introduced; no em-dashes
  • Commits follow Conventional Commits, imperative mood, with no AI-assistant mentions

Related issues

Closes #3

@aaronstevenwhite aaronstevenwhite merged commit c83aa20 into main Jun 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Aggregate per-dataset changelog entries with category sections and ChangeItem.targets

1 participant