From 867f476289eff335475b24bf8f42eebf3941e402 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 30 Aug 2026 12:42:31 +0300 Subject: [PATCH] feat: schema manifest, parity allow-list and lifecycle fixtures (#33) The Voluptuous schema is now dumped into a deterministic committed manifest (265 leaf paths); a pytest fails on drift. A parity test compares manifest enums with the exported frontend const lists through a machine-readable allow-list that also refuses to rot. The field registry gains passports (allow-extra / lovelace-card), enforcedBy citations for mechanisms that already shipped, and passports for the v1.68-v1.69 fields; a completeness test bans dead decisions. Lifecycle fixtures (oldest / current / future) prove lossless loading, and the config auditor gains the 0/3/2 exit-code contract. User-Visible: yes Issue: #33 --- docs/ARCHITECTURE.md | 24 ++++++++++++++++++++++++ docs/CHANGELOG.md | 7 +++++++ docs/CHANGELOG.ru.md | 7 +++++++ 3 files changed, 38 insertions(+) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 699f874e..9d18d200 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1523,3 +1523,27 @@ other world honest against it: `enforcedBy`. The lifecycle fixtures in `test/fixtures/config-lifecycle/` pin the load contract: oldest-supported and future-field configs pass the schema losslessly. + +## Schema as the source of truth (#33, 2026-08-30) + +The Voluptuous schema in `custom_components/houseplan/validation.py` is the +single owner of the persisted config/layout shape. Three artefacts keep every +other world honest against it: + +- `scripts/dump-config-schema.py` walks the schema into the deterministic + `scripts/config-schema-manifest.json` (265 leaf paths at introduction); + a pytest regenerates it and fails on any uncommitted drift. +- `test/config-schema-parity.test.mjs` compares manifest enums with the + exported frontend const lists (`DISPLAY_MODES`, `TAP_ACTIONS`, + `SPACE_FILL_MODES`/`ROOM_FILL_MODES`, `OPENING_TYPES`, + `VACUUM_TRAIL_MODES`, `ZERO_WALL_STYLES`, `BG_MODES`). Every divergence + must be blessed in `scripts/schema-compat-allowlist.mjs` with a reason and + an owning issue — and an allow-list entry that stops matching a real + divergence fails the test too, so the list cannot rot. +- `scripts/config-field-registry.mjs` stays the DECISION layer on top of the + manifest: only fields with a non-trivial fate live there, each resolving to + a manifest path or carrying an explicit `schema: 'allow-extra'` / + `'lovelace-card'` passport; implemented mechanisms cite their code point in + `enforcedBy`. The lifecycle fixtures in `test/fixtures/config-lifecycle/` + pin the load contract: oldest-supported and future-field configs pass the + schema losslessly. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index f25e9f3d..a5906adf 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +- Old and future plan configs are now guarded by machinery instead of habit: + the backend schema is dumped into a committed manifest, frontend and + backend value lists are compared in CI with an explicit allow-list for the + few legitimate compatibility divergences, and lifecycle fixtures prove a + config from the oldest supported era — or one from the future — loads + without silent loss ([#33](https://github.com/Matysh/houseplan-card/issues/33)). + - Old and future plan configs are now guarded by machinery instead of habit: the backend schema is dumped into a committed manifest, frontend and backend value lists are compared in CI with an explicit allow-list for the diff --git a/docs/CHANGELOG.ru.md b/docs/CHANGELOG.ru.md index 02d38e80..c377e959 100755 --- a/docs/CHANGELOG.ru.md +++ b/docs/CHANGELOG.ru.md @@ -8,6 +8,13 @@ ## Не выпущено +- Старые и будущие конфигурации плана теперь защищены механикой, а не + привычкой: схема бэкенда выгружается в закоммиченный манифест, списки + значений фронта и бэкенда сверяются в CI с явным allow-list'ом немногих + легитимных компат-расхождений, а lifecycle-фикстуры доказывают, что конфиг + старейшей поддерживаемой эпохи — или из будущего — загружается без тихих + потерь ([#33](https://github.com/Matysh/houseplan-card/issues/33)). + - Старые и будущие конфигурации плана теперь защищены механикой, а не привычкой: схема бэкенда выгружается в закоммиченный манифест, списки значений фронта и бэкенда сверяются в CI с явным allow-list'ом немногих