docs(changelog): recap session 2026-05-20 tech-debt cleanup

Consolidate the five domain-purity refactors of the session under
[Unreleased]: RuleScopeLevel enum, FilePath VO post_init, Language
strict + from_raw, ParsedRelease.normalised → clean, ParsedRelease
enum strictness. Removes the duplicate min_movie_size_bytes entry
(now sits under its proper Removed section).
This commit is contained in:
2026-05-20 23:57:06 +02:00
parent 757e4045ee
commit 688c37bbec
+42 -11
View File
@@ -15,17 +15,6 @@ callers).
## [Unreleased] ## [Unreleased]
### Removed
- **`settings.min_movie_size_bytes` retiré.** Le champ Pydantic + son
validator n'avaient plus aucun consommateur (l'ancien
`MovieService.validate_movie_file` ayant été supprimé lors d'une
refonte précédente). La règle "est-ce un vrai film ou un sample"
est désormais portée par l'exclusion par extension
(`application/release/supported_media.py`) et le PoP. Si on a un
jour besoin d'un seuil de taille, il ira dans un YAML knowledge,
pas dans `settings`.
### Fixed ### Fixed
- **Multi-episode chain (e.g. `S14E09E10E11`) now collapses to a full - **Multi-episode chain (e.g. `S14E09E10E11`) now collapses to a full
@@ -66,6 +55,48 @@ callers).
depends on the Protocol, infrastructure provides the YAML-backed depends on the Protocol, infrastructure provides the YAML-backed
adapter. Tests in `tests/infrastructure/test_language_registry.py`. adapter. Tests in `tests/infrastructure/test_language_registry.py`.
### Changed
- **`RuleScope.level` is now an enum (`RuleScopeLevel`).** The set of
valid levels (global, release_group, movie, show, season, episode)
was documented only in a docstring comment and validated nowhere.
`RuleScopeLevel(str, Enum)` keeps wire compatibility (YAML
serialization, `.value` access) while making the closed set explicit
to type-checkers and IDEs. `to_dict()` emits `.value` strings so
YAML output is unchanged.
- **`FilePath` VO uses `__post_init__` instead of a hand-rolled
`__init__`.** Same public API (accepts `str | Path`), same behavior,
but the dataclass-generated `__init__` is no longer bypassed. One
less smell in the shared VOs.
- **`Language` VO is strict by default; `Language.from_raw()` factory
for normalization.** The previous `__post_init__` mutated `iso` and
`aliases` via `object.__setattr__` on a frozen dataclass — a code
smell hiding behind the dataclass facade. Split: the direct
constructor now rejects un-normalized input (uppercase iso,
whitespace in aliases, etc.), and `Language.from_raw()` handles
arbitrary YAML/user input. Only one caller (LanguageRegistry loading
the ISO YAML) needed migration.
- **`ParsedRelease.normalised` renamed to `clean`.** The field name
promised "dots instead of spaces" but in practice held
`raw - site_tag - apostrophes` — only used by `season_folder_name()`.
Renamed and docstring corrected.
- **`ParsedRelease.media_type` / `parse_path` are strict enums.** The
fields were already typed as `MediaTypeToken` / `ParsePath`, but a
tolerant `__post_init__` coerced raw strings. With both classes
being `(str, Enum)`, the coercion served no purpose. Strict
constructor; `.value` no longer passed at call sites; dropped the
unused `_VALID_MEDIA_TYPES` / `_VALID_PARSE_PATHS` lookup tables.
### Removed
- **`settings.min_movie_size_bytes`** — orphan Pydantic field +
validator. Its only consumer (`MovieService.validate_movie_file`)
had been removed during an earlier refactor. The "real movie vs
sample" rule now lives in extension-based exclusion
(`application/release/supported_media.py`) and PoP. If a size
threshold is ever needed, it'll go in a knowledge YAML, not in
`settings`.
### Internal ### Internal
- **Flattened `alfred.domain.shared.media/` package into a single - **Flattened `alfred.domain.shared.media/` package into a single