feat(author): aggregate per-dataset changelog entries with category sections and ChangeItem.targets#4
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.entryper dataset anchor from the diffs of those component records. It also cuts the0.3.0release. Follows from #1 (which generates one entry per changed record).Changes
lairs/author/changelog.py. NewComponentChangevalue model (uri,collection,field_diff) andbuild_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)intoChangeSections, summarises each category's changes into countedChangeItems whosetargetspoint 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 fromprevious_version. An aggregate with no real component change does not bump and emits no sections (idempotent).description(for example "Added features to 25 ontology records") and a bounded, representative set oftargetscapped attargets_per_item(Noneomits 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.0.2.xalready ships:diff_record,_category_for/_CATEGORY_BY_NAMESPACE, andBumpClassifier.classifyover the multi-component{uri: changes}mapping. Existing per-recordbuild_entry/publish(changelog=True)behaviour is untouched.pyproject.toml, the_FALLBACK_VERSIONliteral,uv.lock, andCHANGELOG.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 upstreamversion: str, and bump overrides.Type of change
Checklist
uv run ruff format --check lairs testspassesuv run ruff check lairs testspasses (includingANN401; noAnyin annotations)uv run ty check --error-on-warningpassesuv run pytestpasses (1078 passed, 71 skipped)uv run pytest --run-integration -m integrationpasses against the Docker test PDS (71 passed)uv run --group docs mkdocs build --strictpassestests/CHANGELOG.mdupdated (a new## [0.3.0]release section)@dataclass,pydantic,Any, orobjectannotation introduced; no em-dashesRelated issues
Closes #3